force curve comparison
This commit is contained in:
@@ -5,7 +5,7 @@ from rowers.metrics import rowingmetrics, metricsdicts
|
||||
from scipy.spatial import ConvexHull, Delaunay
|
||||
from scipy.stats import linregress, percentileofscore
|
||||
from pytz import timezone as tz, utc
|
||||
from rowers.models import course_spline, VirtualRaceResult, InStrokeAnalysis
|
||||
from rowers.models import course_spline, VirtualRaceResult, InStrokeAnalysis, ForceCurveAnalysis
|
||||
from bokeh.palettes import Category20c, Category10
|
||||
from bokeh.layouts import layout, widgetbox
|
||||
from bokeh.resources import CDN, INLINE
|
||||
@@ -813,7 +813,11 @@ def interactive_activitychart2(workouts, startdate, enddate, stack='type', toolb
|
||||
return script, div
|
||||
|
||||
|
||||
def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter'):
|
||||
def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter',
|
||||
spm_min=15, spm_max=45,
|
||||
notes='',
|
||||
dist_min=0,dist_max=0,
|
||||
work_min=0,work_max=1500):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||
|
||||
ids = [int(w.id) for w in theworkouts]
|
||||
@@ -1413,9 +1417,18 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter'
|
||||
lengthlabel.text = 'Length: '+length.toFixed(2)
|
||||
efflengthlabel.text = 'Effective Length: '+efflength.toFixed(2)
|
||||
|
||||
console.log(count);
|
||||
console.log(multilines['x'].length);
|
||||
console.log(multilines['y'].length);
|
||||
// console.log(count);
|
||||
// console.log(multilines['x'].length);
|
||||
// console.log(multilines['y'].length);
|
||||
|
||||
// change DOM elements
|
||||
document.getElementById("id_spm_min").value = minspm;
|
||||
document.getElementById("id_spm_max").value = maxspm;
|
||||
document.getElementById("id_dist_min").value = mindist;
|
||||
document.getElementById("id_dist_max").value = maxdist;
|
||||
document.getElementById("id_notes").value = annotation;
|
||||
document.getElementById("id_work_min").value = minwork;
|
||||
document.getElementById("id_work_max").value = maxwork;
|
||||
|
||||
// source.trigger('change');
|
||||
source.change.emit();
|
||||
@@ -1425,40 +1438,43 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter'
|
||||
""")
|
||||
|
||||
annotation = TextInput(
|
||||
width=140, title="Type your plot notes here", value="")
|
||||
width=140, title="Type your plot notes here", value="", name="annotation")
|
||||
annotation.js_on_change('value', callback)
|
||||
callback.args["annotation"] = annotation
|
||||
|
||||
slider_spm_min = Slider(width=140, start=15.0, end=55, value=15.0, step=.1,
|
||||
title="Min SPM")
|
||||
slider_spm_min = Slider(width=140, start=15.0, end=55, value=15, step=.1,
|
||||
title="Min SPM", name="min_spm_slider")
|
||||
slider_spm_min.js_on_change('value', callback)
|
||||
callback.args["minspm"] = slider_spm_min
|
||||
|
||||
slider_spm_max = Slider(width=140, start=15.0, end=55, value=55.0, step=.1,
|
||||
title="Max SPM")
|
||||
slider_spm_max = Slider(width=140, start=15.0, end=55, value=55, step=.1,
|
||||
title="Max SPM", name="max_spm_slider")
|
||||
slider_spm_max.js_on_change('value', callback)
|
||||
callback.args["maxspm"] = slider_spm_max
|
||||
|
||||
slider_work_min = Slider(width=140, start=0, end=1500, value=0, step=10,
|
||||
title="Min Work per Stroke")
|
||||
title="Min Work per Stroke", name="min_work_slider")
|
||||
slider_work_min.js_on_change('value', callback)
|
||||
callback.args["minwork"] = slider_work_min
|
||||
|
||||
slider_work_max = Slider(width=140, start=0, end=1500, value=1500, step=10,
|
||||
title="Max Work per Stroke")
|
||||
title="Max Work per Stroke", name="max_work_slider")
|
||||
slider_work_max.js_on_change('value', callback)
|
||||
callback.args["maxwork"] = slider_work_max
|
||||
|
||||
distmax = 100+100*int(rowdata['distance'].max()/100.)
|
||||
|
||||
slider_dist_min = Slider(width=140, start=0, end=distmax, value=0, step=50,
|
||||
title="Min Distance")
|
||||
title="Min Distance", name="min_dist_slider")
|
||||
slider_dist_min.js_on_change('value', callback)
|
||||
callback.args["mindist"] = slider_dist_min
|
||||
|
||||
if dist_max == 0:
|
||||
dist_max = distmax
|
||||
|
||||
slider_dist_max = Slider(width=140, start=0, end=distmax, value=distmax,
|
||||
step=50,
|
||||
title="Max Distance")
|
||||
title="Max Distance", name="max_dist_slider")
|
||||
slider_dist_max.js_on_change('value', callback)
|
||||
callback.args["maxdist"] = slider_dist_max
|
||||
|
||||
@@ -4078,6 +4094,120 @@ def interactive_streamchart(id=0, promember=0):
|
||||
|
||||
return [script, div]
|
||||
|
||||
def forcecurve_multi_interactive_chart(selected):
|
||||
df_plot = pd.DataFrame()
|
||||
ids = [analysis.id for analysis in selected]
|
||||
|
||||
columns = ['catch', 'slip', 'wash', 'finish', 'averageforce',
|
||||
'peakforceangle', 'peakforce', 'spm', 'distance',
|
||||
'workoutstate', 'driveenergy']
|
||||
|
||||
for analysis in selected:
|
||||
workstrokesonly = not analysis.include_rest_strokes
|
||||
spm_min = analysis.spm_min
|
||||
spm_max = analysis.spm_max
|
||||
dist_min = analysis.dist_min
|
||||
dist_max = analysis.dist_max
|
||||
work_min = analysis.work_min
|
||||
work_max = analysis.work_max
|
||||
rowdata = dataprep.getsmallrowdata_db(columns, ids=[analysis.workout.id],
|
||||
workstrokesonly=workstrokesonly)
|
||||
|
||||
rowdata = rowdata[rowdata['spm']>spm_min]
|
||||
rowdata = rowdata[rowdata['spm']<spm_max]
|
||||
rowdata = rowdata[rowdata['driveenergy']>work_min]
|
||||
rowdata = rowdata[rowdata['driveenergy']<work_max]
|
||||
rowdata = rowdata[rowdata['distance']<dist_max]
|
||||
rowdata = rowdata[rowdata['distance']>dist_min]
|
||||
|
||||
catchav = rowdata['catch'].median()
|
||||
finishav = rowdata['finish'].median()
|
||||
washav = (rowdata['finish']-rowdata['wash']).median()
|
||||
slipav = (rowdata['slip']+rowdata['catch']).median()
|
||||
peakforceav = rowdata['peakforce'].median()
|
||||
peakforceangleav = rowdata['peakforceangle'].median()
|
||||
thresholdforce = 100 if 'x' in analysis.workout.boattype else 200
|
||||
x = [catchav,
|
||||
slipav,
|
||||
peakforceangleav,
|
||||
washav,
|
||||
finishav]
|
||||
|
||||
y = [0, thresholdforce,
|
||||
peakforceav,
|
||||
thresholdforce, 0]
|
||||
|
||||
xname = 'x_'+str(analysis.id)
|
||||
yname = 'y_'+str(analysis.id)
|
||||
|
||||
df_plot[xname] = x
|
||||
df_plot[yname] = y
|
||||
|
||||
source = ColumnDataSource(
|
||||
df_plot
|
||||
)
|
||||
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
||||
plot = Figure(plot_width=920,tools=TOOLS,
|
||||
toolbar_location='above',
|
||||
toolbar_sticky=False)
|
||||
|
||||
plot.sizing_mode = 'stretch_both'
|
||||
|
||||
# add watermark
|
||||
watermarkurl = "/static/img/logo7.png"
|
||||
|
||||
watermarkrange = Range1d(start=0, end=1)
|
||||
watermarkalpha = 0.6
|
||||
watermarkx = 0.99
|
||||
watermarky = 0.01
|
||||
watermarkw = 184
|
||||
watermarkh = 35
|
||||
watermarkanchor = 'bottom_right'
|
||||
plot.extra_y_ranges = {"watermark": watermarkrange}
|
||||
plot.extra_x_ranges = {"watermark": watermarkrange}
|
||||
|
||||
plot.image_url([watermarkurl], watermarkx, watermarky,
|
||||
watermarkw, watermarkh,
|
||||
global_alpha=watermarkalpha,
|
||||
w_units='screen',
|
||||
h_units='screen',
|
||||
anchor=watermarkanchor,
|
||||
dilate=True,
|
||||
x_range_name="watermark",
|
||||
y_range_name="watermark",
|
||||
)
|
||||
|
||||
colors = itertools.cycle(palette)
|
||||
|
||||
try:
|
||||
items = itertools.izip(ids, colors)
|
||||
except AttributeError:
|
||||
items = zip(ids, colors)
|
||||
|
||||
for id, color in items:
|
||||
xname = 'x_'+str(id)
|
||||
yname = 'y_'+str(id)
|
||||
analysis = ForceCurveAnalysis.objects.get(id=id)
|
||||
legendlabel = '{name}'.format(
|
||||
name = analysis.name,
|
||||
)
|
||||
if analysis.notes:
|
||||
legendlabel = '{name} - {notes}'.format(
|
||||
name = analysis.name,
|
||||
notes = analysis.notes
|
||||
)
|
||||
plot.line(xname,yname,source=source,legend_label=legendlabel,
|
||||
line_width=2, color=color)
|
||||
|
||||
plot.legend.location = "top_left"
|
||||
plot.xaxis.axis_label = "Angle"
|
||||
plot.yaxis.axis_label = "Force (N)"
|
||||
|
||||
script, div = components(plot)
|
||||
|
||||
return (script, div)
|
||||
|
||||
def instroke_multi_interactive_chart(selected):
|
||||
df_plot = pd.DataFrame()
|
||||
ids = [analysis.id for analysis in selected]
|
||||
|
||||
Reference in New Issue
Block a user