rough version of comparison
This commit is contained in:
@@ -264,5 +264,11 @@ axlabels = list(axlabels.items())
|
||||
|
||||
|
||||
class ChartParamChoiceForm(forms.Form):
|
||||
plotchoices = (
|
||||
('line','Line Plot'),
|
||||
('scatter','Scatter Plot'),
|
||||
)
|
||||
xparam = forms.ChoiceField(choices=axlabels,initial='distance')
|
||||
yparam = forms.ChoiceField(choices=axlabels,initial='hr')
|
||||
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter')
|
||||
teamid = forms.IntegerField(widget=forms.HiddenInput())
|
||||
|
||||
@@ -1582,7 +1582,8 @@ def interactive_bar_chart(id=0,promember=0):
|
||||
return [script,div]
|
||||
|
||||
def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
|
||||
promember=0):
|
||||
promember=0,
|
||||
labeldict=None):
|
||||
columns = [xparam,yparam,
|
||||
'ftime','distance','fpace',
|
||||
'power','hr','spm',
|
||||
@@ -1636,21 +1637,49 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
|
||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
||||
tools=TOOLS,
|
||||
toolbar_location="above",
|
||||
plot_width=920,
|
||||
toolbar_sticky=False)
|
||||
|
||||
colors = itertools.cycle(palette)
|
||||
|
||||
cntr = 0
|
||||
|
||||
for id,color in itertools.izip(ids,colors):
|
||||
group = datadf[datadf['workoutid']==int(id)].copy()
|
||||
group.sort_values(by='time',ascending=True,inplace=True)
|
||||
group['x'] = group[xparam]
|
||||
group['y'] = group[yparam]
|
||||
|
||||
ymean = group['y'].mean()
|
||||
ylabel = Label(x=100,y=70+20*cntr,
|
||||
x_units='screen',y_units='screen',
|
||||
text=yparam+": {ymean:6.2f}".format(ymean=ymean),
|
||||
background_fill_alpha=.7,
|
||||
text_color=color,
|
||||
)
|
||||
if yparam != 'time' and yparam != 'pace':
|
||||
plot.add_layout(ylabel)
|
||||
|
||||
print cntr,id,len(group),ymean
|
||||
|
||||
source = ColumnDataSource(
|
||||
group
|
||||
)
|
||||
plot.line('x','y',source=source,color=color,legend=str(id))
|
||||
|
||||
plot.legend.location='top_left'
|
||||
if labeldict:
|
||||
legend=labeldict[id]
|
||||
else:
|
||||
legend=str(id)
|
||||
|
||||
if plottype=='line':
|
||||
plot.line('x','y',source=source,color=color,legend=legend)
|
||||
else:
|
||||
plot.scatter('x','y',source=source,color=color,legend=legend,
|
||||
fill_alpha=0.4,line_color=None)
|
||||
|
||||
cntr += 1
|
||||
|
||||
plot.legend.location='bottom_right'
|
||||
plot.xaxis.axis_label = axlabels[xparam]
|
||||
plot.yaxis.axis_label = axlabels[yparam]
|
||||
|
||||
|
||||
@@ -39,15 +39,18 @@ from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SEC
|
||||
def ewmovingaverage(interval,window_size):
|
||||
# Experimental code using Exponential Weighted moving average
|
||||
|
||||
intervaldf = pd.DataFrame({'v':interval})
|
||||
idf_ewma1 = intervaldf.ewm(span=window_size)
|
||||
idf_ewma2 = intervaldf[::-1].ewm(span=window_size)
|
||||
try:
|
||||
intervaldf = pd.DataFrame({'v':interval})
|
||||
idf_ewma1 = intervaldf.ewm(span=window_size)
|
||||
idf_ewma2 = intervaldf[::-1].ewm(span=window_size)
|
||||
|
||||
i_ewma1 = idf_ewma1.mean().ix[:,'v']
|
||||
i_ewma2 = idf_ewma2.mean().ix[:,'v']
|
||||
|
||||
i_ewma1 = idf_ewma1.mean().ix[:,'v']
|
||||
i_ewma2 = idf_ewma2.mean().ix[:,'v']
|
||||
|
||||
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
|
||||
interval2 = np.mean( interval2, axis=0) # average
|
||||
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
|
||||
interval2 = np.mean( interval2, axis=0) # average
|
||||
except ValueError:
|
||||
interval2 = interval
|
||||
|
||||
return interval2
|
||||
|
||||
|
||||
@@ -6,57 +6,57 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
||||
<script async="true" type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
||||
<script async="true" type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
{{ interactiveplot |safe }}
|
||||
{{ interactiveplot |safe }}
|
||||
|
||||
<script>
|
||||
// Set things up to resize the plot on a window resize. You can play with
|
||||
// the arguments of resize_width_height() to change the plot's behavior.
|
||||
var plot_resize_setup = function () {
|
||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
||||
var plot = Bokeh.index[plotid];
|
||||
var plotresizer = function() {
|
||||
// arguments: use width, use height, maintain aspect ratio
|
||||
plot.resize_width_height(true, false, false);
|
||||
};
|
||||
window.addEventListener('resize', plotresizer);
|
||||
plotresizer();
|
||||
};
|
||||
window.addEventListener('load', plot_resize_setup);
|
||||
</script>
|
||||
<style>
|
||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
||||
html, body {height: 100%; margin:5px;}
|
||||
</style>
|
||||
<script>
|
||||
// Set things up to resize the plot on a window resize. You can play with
|
||||
// the arguments of resize_width_height() to change the plot's behavior.
|
||||
var plot_resize_setup = function () {
|
||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
||||
var plot = Bokeh.index[plotid];
|
||||
var plotresizer = function() {
|
||||
// arguments: use width, use height, maintain aspect ratio
|
||||
plot.resize_width_height(true, false, false);
|
||||
};
|
||||
window.addEventListener('resize', plotresizer);
|
||||
plotresizer();
|
||||
};
|
||||
window.addEventListener('load', plot_resize_setup);
|
||||
</script>
|
||||
<style>
|
||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
||||
html, body {height: 100%; margin:5px;}
|
||||
</style>
|
||||
|
||||
|
||||
<div id="workouts" class="grid_12 alpha">
|
||||
|
||||
|
||||
<h1>Interactive Plot</h1>
|
||||
|
||||
{% if user.is_authenticated and mayedit %}
|
||||
<div class="grid_2 alpha">
|
||||
<p>
|
||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit Workout</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid_2 suffix_2 omega">
|
||||
<p>
|
||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced Edit</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="theplot" class="grid_12 alpha flexplot">
|
||||
|
||||
|
||||
<h1>Interactive Plot</h1>
|
||||
|
||||
{% if user.is_authenticated and mayedit %}
|
||||
<div class="grid_2 alpha">
|
||||
<p>
|
||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit Workout</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid_2 suffix_2 omega">
|
||||
<p>
|
||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced Edit</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="theplot" class="grid_12 alpha flexplot">
|
||||
{{ the_div|safe }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -112,6 +112,13 @@
|
||||
</div>
|
||||
|
||||
<div class="grid_4 omega">
|
||||
{% if team %}
|
||||
<div class="grid_4" id="teambuttons">
|
||||
<div class="grid_3 alpha">
|
||||
<a class="button gray small" href="/rowers/team-compare-select/team/{{ team.id }}/">Multi Workout Compare</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="grid_4" id="announcements">
|
||||
{% if announcements %}
|
||||
<h3>What's New?</h3>
|
||||
|
||||
@@ -6,44 +6,53 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
||||
<script async="true" type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
||||
<script async="true" type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
{{ interactiveplot |safe }}
|
||||
{{ interactiveplot |safe }}
|
||||
|
||||
<script>
|
||||
// Set things up to resize the plot on a window resize. You can play with
|
||||
// the arguments of resize_width_height() to change the plot's behavior.
|
||||
var plot_resize_setup = function () {
|
||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
||||
var plot = Bokeh.index[plotid];
|
||||
var plotresizer = function() {
|
||||
// arguments: use width, use height, maintain aspect ratio
|
||||
plot.resize_width_height(true, false, false);
|
||||
};
|
||||
window.addEventListener('resize', plotresizer);
|
||||
plotresizer();
|
||||
};
|
||||
window.addEventListener('load', plot_resize_setup);
|
||||
</script>
|
||||
<style>
|
||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
||||
html, body {height: 100%; margin:5px;}
|
||||
</style>
|
||||
<script>
|
||||
// Set things up to resize the plot on a window resize. You can play with
|
||||
// the arguments of resize_width_height() to change the plot's behavior.
|
||||
var plot_resize_setup = function () {
|
||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
||||
var plot = Bokeh.index[plotid];
|
||||
var plotresizer = function() {
|
||||
// arguments: use width, use height, maintain aspect ratio
|
||||
plot.resize_width_height(true, false, false);
|
||||
};
|
||||
window.addEventListener('resize', plotresizer);
|
||||
plotresizer();
|
||||
};
|
||||
window.addEventListener('load', plot_resize_setup);
|
||||
</script>
|
||||
<style>
|
||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
||||
html, body {height: 100%; margin:5px;}
|
||||
</style>
|
||||
|
||||
|
||||
<div id="workouts" class="grid_12 alpha">
|
||||
|
||||
|
||||
<h1>Interactive Comparison</h1>
|
||||
|
||||
|
||||
<div id="theplot" class="grid_12 alpha flexplot">
|
||||
<h1>Interactive Comparison</h1>
|
||||
<div class="grid_2 alpha">
|
||||
<a class="button gray small" href="/rowers/list-workouts/team/{{ teamid }}/">Team Workouts</a>
|
||||
</div>
|
||||
<div class="grid_2">
|
||||
<a class="button gray small" href="/rowers/team-compare-select/team/{{ teamid }}/">Multi Compare</a>
|
||||
</div>
|
||||
<div class="grid_2 suffix_6 omega">
|
||||
<a class="button gray small" href="/rowers/team/{{ teamid }}/">Team Page</a>
|
||||
</div>
|
||||
<div class="grid_12 alpha">
|
||||
|
||||
|
||||
|
||||
<div id="theplot" class="grid_12 alpha flexplot">
|
||||
{{ the_div|safe }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
|
||||
<div class="grid_12">
|
||||
|
||||
Select start and end date for a date range:
|
||||
<div class="grid_4 alpha">
|
||||
<div class="grid_4 alpha">
|
||||
|
||||
{% if team %}
|
||||
<form enctype="multipart/form-data" action="/rowers/team-compare-select/team/{{ team.id }}/" method="post">
|
||||
@@ -69,12 +68,25 @@
|
||||
<p> No workouts found </p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="form_settings" class="grid_4 alpha">
|
||||
<div id="form_settings" class="grid_4 alpha">
|
||||
<p><b>Warning: You are on an experimental part of the site. Use at your own risk.</b></p>
|
||||
<p>Select two or more workouts on the left, set your plot settings below,
|
||||
and press submit"</p>
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{{ chartform.as_table }}
|
||||
</table>
|
||||
<input name='workoutselectform' class="button green" type="submit" value="Submit">
|
||||
<div class="grid_1 prefix_2 suffix_1">
|
||||
<p>
|
||||
<input name='workoutselectform' class="button green" type="submit" value="Submit">
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid_4">
|
||||
<p>You can use the date and search forms above to search through all
|
||||
workouts from this team.</p>
|
||||
<p>TIP: Agree with your team members to put tags (e.g. '8x500m') in the notes section of
|
||||
your workouts. That makes it easy to search.</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -2036,7 +2036,7 @@ def team_comparison_select(request,
|
||||
form = WorkoutMultipleCompareForm()
|
||||
form.fields["workouts"].queryset = workouts
|
||||
|
||||
chartform = ChartParamChoiceForm()
|
||||
chartform = ChartParamChoiceForm(initial={'teamid':theteam.id})
|
||||
|
||||
return render(request, 'team_compare_select.html',
|
||||
{'workouts': workouts,
|
||||
@@ -2067,15 +2067,25 @@ def multi_compare_view(request):
|
||||
workouts = cd['workouts']
|
||||
xparam = chartform.cleaned_data['xparam']
|
||||
yparam = chartform.cleaned_data['yparam']
|
||||
plottype = chartform.cleaned_data['plottype']
|
||||
teamid = chartform.cleaned_data['teamid']
|
||||
ids = [w.id for w in workouts]
|
||||
labeldict = {
|
||||
w.id: w.__unicode__() for w in workouts
|
||||
}
|
||||
|
||||
res = interactive_multiple_compare_chart(ids,xparam,yparam,
|
||||
promember=promember)
|
||||
promember=promember,
|
||||
plottype=plottype,
|
||||
labeldict=labeldict)
|
||||
script = res[0]
|
||||
div = res[1]
|
||||
|
||||
return render(request,'multicompare.html',
|
||||
{'interactiveplot':script,
|
||||
'the_div':div,
|
||||
'promember':promember,
|
||||
'teamid':teamid,
|
||||
})
|
||||
else:
|
||||
return HttpResponse("Form is not valid")
|
||||
|
||||
Reference in New Issue
Block a user