Skip to content

Commit

Permalink
Display quartiles and extrema as bands on timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Jun 9, 2016
1 parent 11bbaea commit 325a1fd
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 22 deletions.
2 changes: 2 additions & 0 deletions codespeed/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@
# COMP_EXECUTABLES = [
# ('myexe', '21df2423ra'),
# ('myexe', 'L'),]

USE_MEDIAN_BANDS = True # True to enable median bands on Timeline view
100 changes: 90 additions & 10 deletions codespeed/static/js/timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,34 @@ function getColor(exe_id) {
.data('color');
}

function scaleColorAlpha(color, scale) {
var c = $.jqplot.getColorComponents(color);
c[3] = c[3] * scale;
return 'rgba(' + c[0] +', '+ c[1] +', '+ c[2] +', '+ c[3] + ')';
}

function shouldPlotEquidistant() {
return $("#equidistant").is(':checked');
}

function shouldPlotQuartiles() {
return $("#show_quartile_bands").is(':checked');
}

function shouldPlotExtrema() {
return $("#show_extrema_bands").is(':checked');
}

function getConfiguration() {
var config = {
exe: readCheckbox("input[name='executable']:checked"),
base: $("#baseline option:selected").val(),
ben: $("input[name='benchmark']:checked").val(),
env: $("input[name='environments']:checked").val(),
revs: $("#revisions option:selected").val(),
equid: $("#equidistant").is(':checked') ? "on" : "off"
equid: $("#equidistant").is(':checked') ? "on" : "off",
quarts: $("#show_quartile_bands").is(':checked') ? "on" : "off",
extr: $("#show_extrema_bands").is(':checked') ? "on" : "off"
};

var branch = readCheckbox("input[name='branch']:checked");
Expand All @@ -53,25 +69,89 @@ function permalinkToChanges(commitid, executableid, environment) {
function OnMarkerClickHandler(ev, gridpos, datapos, neighbor, plot) {
if($("input[name='benchmark']:checked").val() === "grid") { return false; }
if (neighbor) {
var commitid = neighbor.data[3];
var commitid = neighbor.data[neighbor.data.length-2];
// Get executable ID from the seriesindex array
var executableid = seriesindex[neighbor.seriesIndex];
var environment = $("input[name='environments']:checked").val();
permalinkToChanges(commitid, executableid, environment);
}
}

function getHighlighterConfig(median) {
if (median) {
return {
show: true,
tooltipLocation: 'nw',
yvalues: 7,
formatString:'<table class="jqplot-highlighter"> <tr><td>date:</td><td>%s</td></tr> <tr><td>median:</td><td>%s</td></tr> <tr><td>max:</td><td>%s</td></tr> <tr><td>Q3:</td><td>%s</td></tr> <tr><td>Q1:</td><td>%s</td></tr> <tr><td>min:</td><td>%s</td></tr> <tr><td>commit:</td><td>%s</td></tr></table>'
};
} else {
return {
show: true,
tooltipLocation: 'nw',
yvalues: 4,
formatString:'<table class="jqplot-highlighter"> <tr><td>date:</td><td>%s</td></tr> <tr><td>result:</td><td>%s</td></tr> <tr><td>std dev:</td><td>%s</td></tr> <tr><td>commit:</td><td>%s</td></tr></table>'
};
}
}

function renderPlot(data) {
var plotdata = [],
series = [],
lastvalues = [];//hopefully the smallest values for determining significant digits.
seriesindex = [];
var hiddenSeries = 0;
var median = data['data_type'] === 'M';
for (var branch in data.branches) {
// NOTE: Currently, only the "default" branch is shown in the timeline
for (var exe_id in data.branches[branch]) {
// FIXME if (branch !== "default") { label += " - " + branch; }
var label = $("label[for*='executable" + exe_id + "']").html();
series.push({"label": label, "color": getColor(exe_id)});
var seriesConfig = {
label: label,
color: getColor(exe_id)
};
if (median) {
$("span.options.median").css("display", "inline");
var mins = new Array();
var maxes = new Array();
var q1s = new Array();
var q3s = new Array();
for (res in data["branches"][branch][exe_id]) {
var date = data["branches"][branch][exe_id][res][0];
var value = data["branches"][branch][exe_id][res][1];
var max = data["branches"][branch][exe_id][res][2];
var q3 = data["branches"][branch][exe_id][res][3];
var q1 = data["branches"][branch][exe_id][res][4];
var min = data["branches"][branch][exe_id][res][5];
if (min !== "")
mins.push([date, min]);
if (max !== "")
maxes.push([date, max]);
if (q1 !== "")
q1s.push([date, q1]);
if (q3 !== "")
q3s.push([date, q3]);
}
var extrema = new Array(mins, maxes);
var quartiles = new Array(q1s, q3s);
if (shouldPlotQuartiles()) {
seriesConfig['rendererOptions'] = {bandData: quartiles};
} else if (shouldPlotExtrema()) {
seriesConfig['rendererOptions'] = {bandData: extrema};
}
if (shouldPlotQuartiles() && shouldPlotExtrema()) {
series.push({
showLabel: false,
showMarker: false,
color: scaleColorAlpha(getColor(exe_id), 0.6),
rendererOptions: {bandData: extrema}
});
plotdata.push(data.branches[branch][exe_id]);
hiddenSeries++;
}
}
series.push(seriesConfig);
seriesindex.push(exe_id);
plotdata.push(data.branches[branch][exe_id]);
lastvalues.push(data.branches[branch][exe_id][0][1]);
Expand Down Expand Up @@ -121,15 +201,10 @@ function renderPlot(data) {
}
},
legend: {show: true, location: 'nw'},
highlighter: {
show: true,
tooltipLocation: 'nw',
yvalues: 4,
formatString:'<table class="jqplot-highlighter"> <tr><td>date:</td><td>%s</td></tr> <tr><td>result:</td><td>%s</td></tr> <tr><td>std dev:</td><td>%s</td></tr> <tr><td>commit:</td><td>%s</td></tr></table>'
},
highlighter: getHighlighterConfig(median),
cursor:{show:true, zoom:true, showTooltip:false, clickReset:true}
};
if (series.length > 4) {
if (series.length > 4 + hiddenSeries) {
// Move legend outside plot area to unclutter
var labels = [];
for (var l in series) {
Expand Down Expand Up @@ -193,6 +268,7 @@ function renderMiniplot(plotid, data) {
function render(data) {
$("#revisions").attr("disabled", false);
$("#equidistant").attr("disabled", false);
$("span.options.median").css("display", "none");
$("#plotgrid").html("");
if(data.error !== "None") {
var h = $("#content").height();//get height for error message
Expand Down Expand Up @@ -254,6 +330,8 @@ function initializeSite(event) {
$("input[name='benchmark']" ).change(updateUrl);
$("input[name='environments']").change(updateUrl);
$("#equidistant" ).change(updateUrl);
$("#show_quartile_bands" ).change(updateUrl);
$("#show_extrema_bands" ).change(updateUrl);
}

function refreshSite(event) {
Expand Down Expand Up @@ -307,6 +385,8 @@ function setValuesOfInputFields(event) {

$("#baselinecolor").css("background-color", baselineColor);
$("#equidistant").prop('checked', valueOrDefault(event.parameters.equid, defaults.equidistant) === "on");
$("#show_quartile_bands").prop('checked', valueOrDefault(event.parameters.quarts, defaults.quartiles) === "on");
$("#show_extrema_bands").prop('checked', valueOrDefault(event.parameters.extr, defaults.extrema) === "on");
}

function init(def) {
Expand Down
14 changes: 13 additions & 1 deletion codespeed/templates/codespeed/timeline.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@
<input id="equidistant" name="equidistant" type="checkbox" />
<label for="equidistant">Equidistant</label>
</span>
{% if use_median_bands %}
<span class="options median" title="Shows quartile bands in the plots" style="display: none">
<input id="show_quartile_bands" type="checkbox" name="show_quartile_bands" checked="checked"/>
<label for="show_quartile_bands">Show quartile bands</label>
</span>
<span class="options median" title="Shows extrema bands in the plots" style="display: none">
<input id="show_extrema_bands" type="checkbox" name="show_extrema_bands" checked="checked"/>
<label for="show_extrema_bands">Show extrema bands</label>
</span>
{% endif %}
<a id="permalink" href="#">Permalink</a>
</div>
<div id="content" class="clearfix">
Expand Down Expand Up @@ -115,7 +125,9 @@
branches: [{% for b in branch_list %}"{{ branch }}", {% endfor %}],
benchmark: "{{ defaultbenchmark }}",
environment: {{ defaultenvironment.id }},
equidistant: "{{ defaultequid }}"
equidistant: "{{ defaultequid }}",
quartiles: "{{ defaultquarts }}",
extrema: "{{ defaultextr }}"
});
});
</script>
Expand Down
56 changes: 45 additions & 11 deletions codespeed/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ def gettimelinedata(request):
'benchmark': bench.name,
'benchmark_id': bench.id,
'benchmark_description': bench.description,
'data_type': bench.data_type,
'units': bench.units,
'lessisbetter': lessisbetter,
'branches': {},
Expand Down Expand Up @@ -288,16 +289,37 @@ def gettimelinedata(request):

results = []
for res in resultquery:
std_dev = ""
if res.std_dev is not None:
std_dev = res.std_dev
results.append(
[
res.revision.date.strftime('%Y/%m/%d %H:%M:%S %z'),
res.value, std_dev,
res.revision.get_short_commitid(), branch
]
)
if bench.data_type == 'M':
val_min = ""
if res.val_min is not None:
val_min = res.val_min
val_max = ""
if res.val_max is not None:
val_max = res.val_max
q1 = ""
if res.q1 is not None:
q1 = res.q1
q3 = ""
if res.q3 is not None:
q3 = res.q3
results.append(
[
res.revision.date.strftime('%Y/%m/%d %H:%M:%S %z'),
res.value, val_max, q3, q1, val_min,
res.revision.get_short_commitid(), branch
]
)
else:
std_dev = ""
if res.std_dev is not None:
std_dev = res.std_dev
results.append(
[
res.revision.date.strftime('%Y/%m/%d %H:%M:%S %z'),
res.value, std_dev,
res.revision.get_short_commitid(), branch
]
)
timeline['branches'][branch][executable] = results
append = True
if baselinerev is not None and append:
Expand Down Expand Up @@ -424,11 +446,20 @@ def timeline(request):
defaultequid = data['equid']
else:
defaultequid = "off"
if 'quarts' in data:
defaultquarts = data['quarts']
else:
defaultquarts = "on"
if 'extr' in data:
defaultextr = data['extr']
else:
defaultextr = "on"

# Information for template
executables = {}
for proj in Project.objects.filter(track=True):
executables[proj] = Executable.objects.filter(project=proj)
use_median_bands = hasattr(settings, 'USE_MEDIAN_BANDS') and settings.USE_MEDIAN_BANDS
return render_to_response('codespeed/timeline.html', {
'checkedexecutables': checkedexecutables,
'defaultbaseline': defaultbaseline,
Expand All @@ -442,7 +473,10 @@ def timeline(request):
'environments': enviros,
'branch_list': branch_list,
'defaultbranch': defaultbranch,
'defaultequid': defaultequid
'defaultequid': defaultequid,
'defaultquarts': defaultquarts,
'defaultextr': defaultextr,
'use_median_bands': use_median_bands,
}, context_instance=RequestContext(request))


Expand Down

0 comments on commit 325a1fd

Please sign in to comment.