[llvm-commits] [zorg] r147463 - in /zorg/trunk/lnt/lnt/server/ui: templates/v4_graph.html views.py

Daniel Dunbar daniel at zuster.org
Tue Jan 3 11:10:15 PST 2012


Author: ddunbar
Date: Tue Jan  3 13:10:15 2012
New Revision: 147463

URL: http://llvm.org/viewvc/llvm-project?rev=147463&view=rev
Log:
[lnt/v0.4] lnt.server.ui/v4: Add graph support for V4 databases.

Added:
    zorg/trunk/lnt/lnt/server/ui/templates/v4_graph.html
Modified:
    zorg/trunk/lnt/lnt/server/ui/views.py

Added: zorg/trunk/lnt/lnt/server/ui/templates/v4_graph.html
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/lnt/lnt/server/ui/templates/v4_graph.html?rev=147463&view=auto
==============================================================================
--- zorg/trunk/lnt/lnt/server/ui/templates/v4_graph.html (added)
+++ zorg/trunk/lnt/lnt/server/ui/templates/v4_graph.html Tue Jan  3 13:10:15 2012
@@ -0,0 +1,107 @@
+{% import "v4_utils.html" as v4_utils %}
+{% import "utils.html" as utils %}
+
+{% set machine = run.machine %}
+
+{% extends "layout.html" %}
+{% set components = [(ts.name, v4_url_for("v4_overview")),
+                     ('machine', v4_url_for("v4_machine", id=machine.id))] %}
+{% block head %}
+        <script src="{{ url_for('.static', filename='popup.js') }}"></script>
+        <script src="{{ url_for('.static', filename='sorttable.js') }}"></script>
+        <script src="{{ url_for('.static', filename='View2D.js') }}"></script>
+{% endblock %}
+
+{% block title %}Graph{% endblock %}
+
+{# Add JS to initialize the graph. #}
+{% block onload %}init(){% endblock %}
+{% block javascript %}
+function init() {
+    graph = new Graph2D("graph");
+    graph.clearColor = [1, 1, 1];
+
+{% for plot in graph_plots %}
+    {{ plot }}
+{% endfor %}
+    
+    graph.xAxis.format = graph.xAxis.formats.normal;
+    graph.draw();
+}
+{% endblock %}
+
+{% block body %}
+
+{% call v4_utils.v4_run_page(ts, machine, run, compare_to, neighboring_runs) %}
+
+{{ utils.render_popup_begin('view_options', 'View Options', true) }}
+<form action="" method="get">
+<b>Show Median Absolute Deviation:</b>
+<input type="checkbox" name="show_mad" value="yes" {{
+       'checked' if options.show_mad}}><br>
+
+<b>Show Standard Deviation:</b>
+<input type="checkbox" name="show_stddev" value="yes" {{
+       'checked' if options.show_stddev}}><br>
+
+<b>Show Linear Regression:</b>
+<input type="checkbox" name="show_linear_regression" value="yes" {{
+       'checked' if options.show_linear_regression}}><br>
+
+<b>Show Points For Failures:</b>
+<input type="checkbox" name="show_failures" value="yes" {{
+       'checked' if options.show_failures}}><br>
+
+<b>Show Sample Points:</b>
+<input type="checkbox" name="show_points" value="yes" {{
+       'checked' if options.show_points}}><br>
+
+<b>Show All Sample Points:</b>
+<input type="checkbox" name="show_all_points" value="yes" {{
+       'checked' if options.show_all_points}}><br>
+
+{# Add all the hidden fields. #}
+{% for name,value in request.args.items() %}
+  {% if name.startswith('test.') %}
+    <input type="hidden" name="{{name}}" value="{{value}}">
+  {% endif %}
+{% endfor %}
+
+<input type="submit" name="submit" value="Update">
+</form>
+{{ utils.render_popup_end() }}
+
+<h3>Graph</h3>
+<table>
+<tr>
+<td rowspan=2 valign="top">
+  <canvas id="graph" width="600" height="400"></canvas>
+</td>
+<td valign="top">
+<table cellspacing=4 border=1>
+<tr><th colspan=3>Test</th></tr>
+{% for name,field_name,col in legend %}
+    <tr>
+      <td bgcolor="{{ '%02x%02x%02x' % (
+                        255*col[0], 255*col[1], 255*col[2]) }}"> </td>
+      <td>{{name}}</td>
+      <td>{{field_name}}</td>
+    </tr>
+{% endfor %}
+</table>
+</td></tr>
+<tr><td align="right" valign="bottom">
+<font size="-2">
+Shift-Left Mouse: Pan<br>
+Alt/Meta-Left Mouse: Zoom<br>
+Wheel: Zoom (<i>Shift Slows</i>)<br>
+</font>
+</td></tr>
+</table>
+<p>
+<b>Plots</b>: {{ num_plots }}<br>
+<b>Num Points</b>: {{ num_points }}<br>
+
+{% endcall %}
+
+{% endblock %}

Modified: zorg/trunk/lnt/lnt/server/ui/views.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/lnt/lnt/server/ui/views.py?rev=147463&r1=147462&r2=147463&view=diff
==============================================================================
--- zorg/trunk/lnt/lnt/server/ui/views.py (original)
+++ zorg/trunk/lnt/lnt/server/ui/views.py Tue Jan  3 13:10:15 2012
@@ -681,6 +681,10 @@
     # Find the neighboring runs, by order.
     prev_runs = list(ts.get_previous_runs_on_machine(run, N = 3))
     next_runs = list(ts.get_next_runs_on_machine(run, N = 3))
+    if prev_runs:
+        compare_to = prev_runs[0]
+    else:
+        compare_to = None
     neighboring_runs = next_runs[::-1] + [run] + prev_runs
 
     # Parse the view options.
@@ -717,7 +721,7 @@
         baseurl=v4_url_for('v4_overview', _external=True),
         was_added=True, will_commit=True, only_html_body=True)
 
-    return render_template("v4_run.html", ts=ts, run=run,
+    return render_template("v4_run.html", ts=ts, run=run, compare_to=compare_to,
                            options=options, neighboring_runs=neighboring_runs,
                            text_report=text_report, html_report=html_report)
 
@@ -732,3 +736,182 @@
         abort(404)
 
     return render_template("v4_order.html", ts=ts, order=order)
+
+ at v4_route("/<int:id>/graph")
+def v4_graph(id):
+    from lnt.server.ui import util
+    from lnt.testing import PASS
+    from lnt.util import stats
+    from lnt.external.stats import stats as ext_stats
+
+    ts = request.get_testsuite()
+    run = ts.query(ts.Run).filter_by(id=id).first()
+    if run is None:
+        abort(404)
+
+    # Find the neighboring runs, by order.
+    prev_runs = list(ts.get_previous_runs_on_machine(run, N = 3))
+    next_runs = list(ts.get_next_runs_on_machine(run, N = 3))
+    if prev_runs:
+        compare_to = prev_runs[0]
+    else:
+        compare_to = None
+    neighboring_runs = next_runs[::-1] + [run] + prev_runs
+
+    # Parse the view options.
+    options = {}
+    options['show_mad'] = show_mad = bool(request.args.get('show_mad'))
+    options['show_stddev'] = show_stddev = bool(request.args.get('show_stddev'))
+    options['show_points'] = show_points = bool(request.args.get('show_points'))
+    options['show_all_points'] = show_all_points = bool(
+        request.args.get('show_all_points'))
+    options['show_linear_regression'] = show_linear_regression = bool(
+        request.args.get('show_linear_regression', True))
+    options['show_failures'] = show_failures = bool(
+        request.args.get('show_failures'))
+
+    # Load the graph parameters.
+    graph_tests = []
+    for name,value in request.args.items():
+        # Tests to graph are passed as test.<test id>=<sample field id>.
+        if not name.startswith(str('test.')):
+            continue
+
+        # Extract the test id string and convert to integers.
+        test_id_str = name[5:]
+        try:
+            test_id = int(test_id_str)
+            field_index = int(value)
+        except:
+            return abort(400)
+
+        # Get the test and the field.
+        if not (0 <= field_index < len(ts.sample_fields)):
+            return abort(400)
+
+        test = ts.query(ts.Test).filter(ts.Test.id == test_id).one()
+        field = ts.sample_fields[field_index]
+
+        graph_tests.append((test, field))
+
+    # Order the plots by test name and then field.
+    graph_tests.sort(key = lambda (t,f): (t.name, f.name))
+
+    # Build the graph data.
+    legend = []
+    graph_plots = []
+    num_points = 0
+    num_plots = len(graph_tests)
+    for i,(test,field) in enumerate(graph_tests):
+        # Determine the base plot color.
+        col = list(util.makeDarkColor(float(i) / num_plots))
+        legend.append((test.name, field.name, tuple(col)))
+
+        # Load all the field values for this test on the same machine.
+        #
+        # FIXME: Don't join to Order here, aggregate this across all the tests
+        # we want to load. Actually, we should just make this a single query.
+        q = ts.query(field.column, ts.Order.ordinal).\
+            join(ts.Run).join(ts.Order).\
+            filter(ts.Run.machine == run.machine).\
+            filter(ts.Sample.test == test)
+
+        # Unless all samples requested, filter out failing tests.
+        if not show_failures:
+            if field.status_field:
+                q = q.filter(field.status_field.column == PASS)
+
+        # Aggregate by run order id.
+        data = util.multidict((r,v)
+                              for v,r in q).items()
+        data.sort()
+
+        # Compute the graph points.
+        errorbar_data = []
+        points_data = []
+        pts = []
+        for x,values in data:
+            pts.append((x, min(values)))
+
+            # Add the individual points, if requested.
+            if show_points:
+                if show_all_points:
+                    for v in values:
+                        points_data.append((x, v))
+                else:
+                    points_data.append((x, min_value))
+
+            # Add the standard deviation error bar, if requested.
+            if show_stddev:
+                mean = stats.mean(values)
+                sigma = stats.standard_deviation(values)
+                errorbar_data.append((x, mean - sigma, mean + sigma))
+
+            # Add the MAD error bar, if requested.
+            if show_mad:
+                med = stats.median(values)
+                mad = stats.median_absolute_deviation(values, med)
+                errorbar_data.append((x, med - mad, med + mad))
+
+        # Add the minimum line plot.
+        num_points += len(data)
+        graph_plots.append("graph.addPlot([%s], %s);" % (
+                        ','.join(['[%.4f,%.4f]' % (t,v)
+                                  for t,v in pts]),
+                        "new Graph2D_LinePlotStyle(1, %r)" % col))
+
+        # Add regression line, if requested.
+        if show_linear_regression:
+            xs = [t for t,v in pts]
+            ys = [v for t,v in pts]
+
+            # We compute the regression line in terms of a normalized X scale.
+            x_min, x_max = min(xs), max(xs)
+            try:
+                norm_xs = [(x - x_min) / (x_max - x_min)
+                           for x in xs]
+            except ZeroDivisionError:
+                norm_xs = xs
+
+            try:
+                info = ext_stats.linregress(norm_xs, ys)
+            except ZeroDivisionError:
+                info = None
+            except ValueError:
+                info = None
+
+            if info is not None:
+                slope, intercept,_,_,_ = info
+
+                reglin_col = [c*.5 for c in col]
+                pts = ','.join('[%.4f,%.4f]' % pt
+                               for pt in [(x_min, 0.0 * slope + intercept),
+                                          (x_max, 1.0 * slope + intercept)])
+                style = "new Graph2D_LinePlotStyle(4, %r)" % ([.7, .7, .7],)
+                graph_plots.append("graph.addPlot([%s], %s);" % (
+                        pts,style))
+                style = "new Graph2D_LinePlotStyle(2, %r)" % (reglin_col,)
+                graph_plots.append("graph.addPlot([%s], %s);" % (
+                        pts,style))
+
+        # Add the points plot, if used.
+        if points_data:
+            pts_col = (0,0,0)
+            graph_plots.append("graph.addPlot([%s], %s);" % (
+                ','.join(['[%.4f,%.4f]' % (t,v)
+                            for t,v in points_data]),
+                "new Graph2D_PointPlotStyle(1, %r)" % (pts_col,)))
+
+        # Add the error bar plot, if used.
+        if errorbar_data:
+            bar_col = [c*.7 for c in col]
+            graph_plots.append("graph.addPlot([%s], %s);" % (
+                ','.join(['[%.4f,%.4f,%.4f]' % (x,y_min,y_max)
+                          for x,y_min,y_max in errorbar_data]),
+                "new Graph2D_ErrorBarPlotStyle(1, %r)" % (bar_col,)))
+
+    return render_template("v4_graph.html", ts=ts, run=run,
+                           compare_to=compare_to, options=options,
+                           num_plots=num_plots, num_points=num_points,
+                           neighboring_runs=neighboring_runs,
+                           graph_plots=graph_plots, legend=legend)





More information about the llvm-commits mailing list