{# A two-metric scatter, rendered as inline SVG with the same figures in a table beneath it. Both axes start at zero and end just above the largest value: UI standards §5 forbids a truncated axis, and a fixed zero origin is the only rule that cannot accidentally exaggerate a difference. Every point is a link to the run it came from, so the chart is part of the drill-down rather than a picture of it. Expects: points (Sequence[ScatterPoint]), chart_id, title, x_label, y_label. #} {% if points %} {% set xmax = (points | map(attribute='x') | max) or 1 %} {% set ymax = (points | map(attribute='y') | max) or 1 %} {% set xspan = (xmax * 1.05) if xmax > 0 else 1 %} {% set yspan = (ymax * 1.05) if ymax > 0 else 1 %}
{{ title }}
{{ title }} {{ points | length }} models. Horizontal axis {{ x_label }} from 0 to {{ '%.4g' % xspan }}; vertical axis {{ y_label }} from 0 to {{ '%.4g' % yspan }}. The same figures are in the table below this chart. {% for point in points %} {% set cx = 40 + (270 * point.x / xspan) %} {% set cy = 150 - (140 * point.y / yspan) %} {{ loop.index }} {% endfor %} 0 {{ '%.4g' % xspan }} {{ points[0].x_unit }} {{ '%.4g' % yspan }} {{ points[0].y_unit }}
{% for point in points %} {% endfor %}
{{ title }} — the chart's figures as text.
# Model {{ x_label }} {{ y_label }} Source
{{ loop.index }} {{ point.label }} {{ '%.4g' % point.x }} {{ point.x_unit }} {{ '%.4g' % point.y }} {{ point.y_unit }} run {{ point.run_id[:8] }}
{% else %}

{{ title }}

Nothing to plot yet: this needs a model with both a quality figure and a {{ x_label }} figure from a completed run. Run native.performance and one quality suite against the same model, then come back.

{% endif %}