Merge branch 'feature/forcecurve' into develop
This commit is contained in:
+13
-1
@@ -723,6 +723,7 @@ class TrendFlexModalForm(forms.Form):
|
||||
required=False)
|
||||
|
||||
|
||||
|
||||
# This form sets options for the summary stats page
|
||||
class StatsOptionsForm(forms.Form):
|
||||
includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False)
|
||||
@@ -1181,9 +1182,20 @@ class FlexOptionsForm(forms.Form):
|
||||
('line','Line Plot'),
|
||||
('scatter','Scatter Plot'),
|
||||
)
|
||||
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter',
|
||||
plottype = forms.ChoiceField(choices=plotchoices,initial='line',
|
||||
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):
|
||||
axchoices = list(
|
||||
|
||||
+266
-42
@@ -17,6 +17,7 @@ from math import pi
|
||||
from django.utils import timezone
|
||||
|
||||
from bokeh.palettes import Dark2_8 as palette
|
||||
from bokeh.models.glyphs import MultiLine
|
||||
import itertools
|
||||
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
|
||||
from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
|
||||
@@ -64,6 +65,7 @@ activate(settings.TIME_ZONE)
|
||||
thetimezone = get_current_timezone()
|
||||
|
||||
from scipy.stats import linregress,percentileofscore
|
||||
from scipy.spatial import ConvexHull,Delaunay
|
||||
from scipy import optimize
|
||||
from scipy.signal import savgol_filter
|
||||
from scipy.interpolate import griddata
|
||||
@@ -373,7 +375,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'):
|
||||
script,div = components(p)
|
||||
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'
|
||||
|
||||
ids = [int(w.id) for w in theworkouts]
|
||||
@@ -407,96 +409,222 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
# quick linear regression
|
||||
# peakforce = slope*peakforceangle + intercept
|
||||
slope, intercept, r,p,stderr = linregress(rowdata['peakforceangle'],rowdata['peakforce'])
|
||||
theta = np.arctan(slope)
|
||||
|
||||
a = rowdata['peakforceangle']-rowdata['peakforceangle'].mean()
|
||||
F = rowdata['peakforce']-rowdata['peakforce'].mean()
|
||||
covariancematrix = np.cov(rowdata['peakforceangle'],y=rowdata['peakforce'])
|
||||
eig_vals, eig_vecs = np.linalg.eig(covariancematrix)
|
||||
|
||||
R = np.array([[np.cos(theta),np.sin(theta)],
|
||||
[-np.sin(theta),np.cos(theta)]])
|
||||
Rinv = np.array([[np.cos(theta),np.sin(theta)],
|
||||
[-np.sin(theta),np.cos(theta)]])
|
||||
a = rowdata['peakforceangle']-rowdata['peakforceangle'].median()
|
||||
F = rowdata['peakforce']-rowdata['peakforce'].median()
|
||||
|
||||
Rinv = eig_vecs
|
||||
R = np.linalg.inv(Rinv)
|
||||
|
||||
x = R[0,0]*a+R[0,1]*F
|
||||
y = R[1,0]*a+R[1,1]*F
|
||||
|
||||
|
||||
x05 = x.quantile(q=0.05)
|
||||
x25 = x.quantile(q=0.25)
|
||||
x75 = x.quantile(q=0.75)
|
||||
x95 = x.quantile(q=0.95)
|
||||
x05 = x.quantile(q=0.01)
|
||||
x25 = x.quantile(q=0.15)
|
||||
x75 = x.quantile(q=0.85)
|
||||
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:
|
||||
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:
|
||||
catchav = 0
|
||||
catch25 = 0
|
||||
catch75 = 0
|
||||
catch05 = 0
|
||||
catch95 = 0
|
||||
|
||||
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:
|
||||
finishav = 0
|
||||
finish25 = 0
|
||||
finish75 = 0
|
||||
finish05 = 0
|
||||
finish95 = 0
|
||||
|
||||
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:
|
||||
washav = 0
|
||||
wash25 = 0
|
||||
wash75 = 0
|
||||
wash05 = 0
|
||||
wash95 = 0
|
||||
|
||||
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:
|
||||
slipav = 0
|
||||
slip25 = 0
|
||||
slip75 = 0
|
||||
slip05 = 0
|
||||
slip95 = 0
|
||||
|
||||
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:
|
||||
peakforceav = 0
|
||||
peakforce25 = 0
|
||||
peakforce75 = 0
|
||||
peakforce05 = 0
|
||||
peakforce95 = 0
|
||||
|
||||
|
||||
try:
|
||||
averageforceav = rowdata['averageforce'].mean()
|
||||
averageforceav = rowdata['averageforce'].median()
|
||||
except KeyError:
|
||||
averageforceav = 0
|
||||
|
||||
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:
|
||||
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)
|
||||
peakforce25 = rowdata['peakforce'].quantile(q=0.25)
|
||||
#thresholdforce /= 4.45 # N to lbs
|
||||
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,
|
||||
catchav+slipav,
|
||||
slipav,
|
||||
peakforceangleav,
|
||||
finishav-washav,
|
||||
washav,
|
||||
finishav]
|
||||
|
||||
thresholdforce = 100 if 'x' in boattype else 200
|
||||
#thresholdforce /= 4.45 # N to lbs
|
||||
y = [0,thresholdforce,
|
||||
peakforceav,
|
||||
thresholdforce,0]
|
||||
|
||||
|
||||
|
||||
source = ColumnDataSource(
|
||||
data = dict(
|
||||
x = x,
|
||||
y = y,
|
||||
))
|
||||
|
||||
sourceslipwash = ColumnDataSource(
|
||||
data = dict(
|
||||
xslip = [slipav,washav],
|
||||
yslip = [thresholdforce,thresholdforce]
|
||||
)
|
||||
)
|
||||
|
||||
sourcetrend = ColumnDataSource(
|
||||
data = dict(
|
||||
x = [peakforceangle25,peakforceangle75],
|
||||
@@ -506,8 +634,8 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
|
||||
sourcefit = ColumnDataSource(
|
||||
data = dict(
|
||||
x = rowdata['peakforceangle'],
|
||||
y = slope*rowdata['peakforceangle']+intercept
|
||||
x = np.array([peakforceangle25,peakforceangle75]),
|
||||
y = slope*np.array([peakforceangle25,peakforceangle75])+intercept
|
||||
)
|
||||
)
|
||||
|
||||
@@ -515,12 +643,29 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
rowdata
|
||||
)
|
||||
|
||||
if plottype == 'scatter':
|
||||
sourcepoints = ColumnDataSource(
|
||||
data = dict(
|
||||
peakforceangle = rowdata['peakforceangle'],
|
||||
peakforce = rowdata['peakforce']
|
||||
)
|
||||
)
|
||||
else:
|
||||
sourcepoints = ColumnDataSource(
|
||||
data = dict(
|
||||
peakforceangle = [],
|
||||
peakforce = []
|
||||
))
|
||||
|
||||
|
||||
sourcerange = ColumnDataSource(
|
||||
data = dict(
|
||||
x2575 = angles2575,
|
||||
y2575 = forces2575,
|
||||
x0595 = angles0595,
|
||||
y0595 = forces0595,
|
||||
)
|
||||
)
|
||||
|
||||
plot = Figure(tools=TOOLS,
|
||||
toolbar_sticky=False,toolbar_location="above")
|
||||
@@ -555,10 +700,57 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
avf = Span(location=averageforceav,dimension='width',line_color='blue',
|
||||
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=sourcetrend,color="blue")
|
||||
plot.line('x','y',source=sourcefit,color="green")
|
||||
|
||||
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',
|
||||
text="Slip: {slipav:6.2f}".format(slipav=slipav),
|
||||
text="Slip: {slipav:6.2f}".format(slipav=slipav-catchav),
|
||||
background_fill_alpha=0.7,
|
||||
background_fill_color='white',
|
||||
text_color='red',
|
||||
)
|
||||
|
||||
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_color='white',
|
||||
text_color='red',
|
||||
@@ -650,6 +842,7 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
callback = CustomJS(args = dict(
|
||||
source=source,
|
||||
source2=source2,
|
||||
sourceslipwash=sourceslipwash,
|
||||
sourcepoints=sourcepoints,
|
||||
avf=avf,
|
||||
avflabel=avflabel,
|
||||
@@ -661,13 +854,26 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
peakforceanglelabel=peakforceanglelabel,
|
||||
annolabel=annolabel,
|
||||
sliderlabel=sliderlabel,
|
||||
plottype=plottype,
|
||||
sourcemultiline=sourcemultiline,
|
||||
sourcemultiline2=sourcemultiline2
|
||||
), code="""
|
||||
var data = source.data
|
||||
var data2 = source2.data
|
||||
var dataslipwash = sourceslipwash.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 y = data['y']
|
||||
|
||||
var xslip = dataslipwash['xslip']
|
||||
|
||||
var spm1 = data2['spm']
|
||||
var distance1 = data2['distance']
|
||||
var driveenergy1 = data2['driveenergy']
|
||||
@@ -682,6 +888,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
var peakforce = data2['peakforce']
|
||||
var averageforce = data2['averageforce']
|
||||
|
||||
var peakforcepoints = datapoints['peakforce']
|
||||
var peakforceanglepoints = datapoints['peakforceangle']
|
||||
|
||||
var annotation = annotation.value
|
||||
var minspm = minspm.value
|
||||
var maxspm = maxspm.value
|
||||
@@ -705,13 +914,23 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
|
||||
datapoints['peakforceangle'] = []
|
||||
datapoints['peakforce'] = []
|
||||
multilines['xs'] = []
|
||||
multilines['ys'] = []
|
||||
|
||||
for (i=0; i<c.length; i++) {
|
||||
if (spm1[i]>=minspm && spm1[i]<=maxspm) {
|
||||
if (distance1[i]>=mindist && distance1[i]<=maxdist) {
|
||||
if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) {
|
||||
if (plottype=='scatter') {
|
||||
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]
|
||||
finishav += finish[i]
|
||||
slipav += slip[i]
|
||||
@@ -736,6 +955,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
data['x'] = [catchav,catchav+slipav,peakforceangleav,finishav-washav,finishav]
|
||||
data['y'] = [0,thresholdforce,peakforceav,thresholdforce,0]
|
||||
|
||||
dataslipwash['xslip'] = [catchav+slipav,finishav-washav]
|
||||
dataslipwash['yslip'] = [thresholdforce,thresholdforce]
|
||||
|
||||
avf.location = averageforceav
|
||||
avflabel.text = 'Favg: '+averageforceav.toFixed(2)
|
||||
catchlabel.text = 'Catch: '+catchav.toFixed(2)
|
||||
@@ -748,7 +970,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
|
||||
|
||||
// source.trigger('change');
|
||||
source.change.emit();
|
||||
sourceslipwash.change.emit()
|
||||
sourcepoints.change.emit();
|
||||
sourcemultiline.change.emit();
|
||||
""")
|
||||
|
||||
annotation = TextInput(title="Type your plot notes here", value="",
|
||||
|
||||
@@ -22,27 +22,24 @@
|
||||
<h1>Empower Force Curve</h1>
|
||||
|
||||
<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">
|
||||
<div id="theplot" class="flexplot">
|
||||
{{ the_div|safe }}
|
||||
</div>
|
||||
|
||||
</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>
|
||||
|
||||
|
||||
|
||||
BIN
Binary file not shown.
@@ -48,6 +48,7 @@ from django.http import (
|
||||
)
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from rowers.forms import (
|
||||
ForceCurveOptionsForm,
|
||||
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
|
||||
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
|
||||
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,
|
||||
|
||||
@@ -26,15 +26,24 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
|
||||
if not promember:
|
||||
return HttpResponseRedirect("/rowers/about/")
|
||||
|
||||
if request.method == 'POST' and 'workstrokesonly' in request.POST:
|
||||
workstrokesonly = request.POST['workstrokesonly']
|
||||
if workstrokesonly == 'True':
|
||||
workstrokesonly = True
|
||||
if request.method == 'POST':
|
||||
form = ForceCurveOptionsForm(request.POST)
|
||||
if form.is_valid():
|
||||
includereststrokes = form.cleaned_data['includereststrokes']
|
||||
plottype = form.cleaned_data['plottype']
|
||||
workstrokesonly = not includereststrokes
|
||||
else:
|
||||
workstrokesonly = False
|
||||
workstrokesonly = True
|
||||
plottype = 'line'
|
||||
else:
|
||||
form = ForceCurveOptionsForm()
|
||||
plottype = 'line'
|
||||
|
||||
script,div,js_resources,css_resources = interactive_forcecurve([row],
|
||||
workstrokesonly=workstrokesonly)
|
||||
script,div,js_resources,css_resources = interactive_forcecurve(
|
||||
[row],
|
||||
workstrokesonly=workstrokesonly,
|
||||
plottype=plottype,
|
||||
)
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
@@ -59,6 +68,7 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
|
||||
{
|
||||
'the_script':script,
|
||||
'rower':r,
|
||||
'form':form,
|
||||
'workout':row,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'active':'nav-workouts',
|
||||
@@ -67,7 +77,6 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
|
||||
'css_res':css_resources,
|
||||
'id':id,
|
||||
'mayedit':mayedit,
|
||||
'workstrokesonly': not workstrokesonly,
|
||||
'teams':get_my_teams(request.user),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user