"""Static HTML and SVG for a job, a receipt, a circuit and Bloch vectors. What a notebook shows when no widget front end is there (a static viewer, a converted page, a front end without the widget extension), and what the widgets show before their script runs. Everything here is drawn from the engine's answers; nothing is computed that the engine did not say. The output is deterministic: the same answer writes the same bytes. """ from __future__ import annotations import math from html import escape from typing import Any, Dict, List, Mapping, Optional, Sequence GOOD = "#10b981" BAD = "#ef4444" BAR = "#7aa0ff" _CARD = ( "font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;" "border:1px solid var(--jp-border-color2,rgba(127,127,127,.35));border-radius:8px;padding:10px 12px;margin:2px 0;max-width:100%;overflow-x:auto" ) _MUTED = "opacity:.7" _MONO = "font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px" #: The most outcomes a histogram lists. TOP = 16 def _num(x: Any) -> str: if isinstance(x, bool) or not isinstance(x, (int, float)): return escape(str(x)) if isinstance(x, int): return str(x) if x == 0: return "0" return f"{x:.6g}" def _badge(ok: bool, yes: str = "verified", no: str = "INVALID") -> str: colour = GOOD if ok else BAD return ( f'{escape(yes if ok else no)}' ) def _short(s: Optional[str], keep: int = 10) -> str: if not s: return "" return s if len(s) <= 2 * keep + 1 else f"{s[:keep]}…{s[-keep:]}" def histogram_svg(counts: Mapping[str, int], shots: int, *, top: int = TOP, frequencies: bool = False) -> str: """Counts as horizontal bars, the most frequent first: the outcome, its bar, its count (or its sampled frequency).""" rows = list(counts.items())[:top] if not rows: return "" label_w = max(7.5 * max(len(k) for k, _ in rows) + 12, 40) bar_w = 260.0 row_h = 18 peak = max(v for _, v in rows) or 1 w = label_w + bar_w + 70 h = row_h * len(rows) + 4 out = [ f'' ] for i, (k, v) in enumerate(rows): y = 2 + i * row_h bw = max(bar_w * v / peak, 1.0) value = f"{v / shots:.4f}" if frequencies and shots else str(v) out.append( f'{escape(k)}' f'{escape(k)}: {v} of {shots}' f'{value}' ) out.append("") return "".join(out) def _table(head: Sequence[str], rows: List[Sequence[str]]) -> str: th = "".join(f'{escape(h)}' for h in head) body = "".join("" + "".join(f'{c}' for c in r) + "" for r in rows) return f'{th}{body}
' def result_html(data: Mapping[str, Any]) -> str: """A result's card from the Result widget's data: its method and accuracy class, its counts as a histogram, its expectation values and amplitudes.""" parts = [f'
'] acc = data.get("accuracy") or "?" parts.append(f'
{escape(str(data.get("method") or "?"))} · accuracy {escape(str(acc))}') if data.get("accuracy_note"): parts.append(f' ({escape(str(data["accuracy_note"]))})') parts.append("
") if data.get("why"): parts.append(f'
{escape(str(data["why"]))}
') counts = data.get("counts") or {} if counts: shots = int(data.get("shots") or 0) listed = min(len(counts), TOP) parts.append(f'
{shots} shots, {data.get("distinct_outcomes", len(counts))} distinct outcomes; the {listed} most frequent:
') parts.append(histogram_svg(counts, shots)) rest = sum(list(counts.values())[TOP:]) + int(data.get("omitted_shots") or 0) if rest: parts.append(f'
{rest} more shots fell on outcomes not drawn
') exps = data.get("expectations") or [] if exps: rows = [] for e in exps: err = "" if e.get("bound") is not None: err = f"± {_num(e['bound'])} (bound)" elif e.get("stderr") is not None: err = f"± {_num(e['stderr'])} (std. error)" rows.append([escape(str(e.get("observable"))), _num(e.get("value")), err]) parts.append(_table(["observable", "value", "error"], rows)) amps = data.get("amplitudes") or [] if amps: parts.append(_table(["basis state", "re", "im", "|a|²"], [[escape(str(a["bits"])), _num(a["re"]), _num(a["im"]), _num(a["re"] ** 2 + a["im"] ** 2)] for a in amps])) if data.get("receipt"): r = data["receipt"] parts.append(f'
receipt {_badge(bool(r.get("valid")))} signed by {escape(_short(r.get("signer"), 14))}') if r.get("demo"): parts.append(f' (the published demo key: it shows the result is unaltered, not who signed it)') parts.append("
") parts.append("
") return "".join(parts) def receipt_html(data: Mapping[str, Any]) -> str: """A receipt's card from the Receipt widget's data.""" ok = bool(data.get("valid")) rows = [ ["signer", f'{escape(str(data.get("signer") or "—"))}'], ["key", escape(str(data.get("key") or "—"))], ["digest", escape(str(data.get("digest") or "—"))], ["signature", escape(_short(data.get("signature"), 16) or "—")], ["form", escape(f"{data.get('alg') or '?'} over {data.get('canon') or 'the first form'} canonical JSON")], ] body = "".join(f'{k}{v}' for k, v in rows) note = "" if data.get("demo"): note = f'
Signed with the published demo key: it shows the result is unaltered, not who signed it.
' what = escape(str(data.get("binds") or "the request and the result as given")) return ( f'
receipt {_badge(ok)} checked here, binding {what}
' f'{body}
{note}
' ) def verification_html(v: Mapping[str, Any]) -> str: return ( f'
receipt {_badge(v.get("valid") is True)} ' f'signed by {escape(str(v.get("signer") or v.get("key") or "?"))}
' ) def circuit_html(data: Mapping[str, Any]) -> str: """The engine's drawing, in a card that scrolls when it is wide.""" return f'
{data["svg"]}
' # -- Bloch vectors ---------------------------------------------------------- #: The view a drawing of Bloch vectors starts from, degrees: turned about z, #: then tilted towards the reader. VIEW = (-35.0, 20.0) def project(v: Sequence[float], azimuth: float, elevation: float) -> tuple: """A point on or in the unit sphere as the reader sees it, in the sphere's radii: (right, up). The same projection the widget draws.""" a, e = math.radians(azimuth), math.radians(elevation) x, y, z = v xr = x * math.cos(a) - y * math.sin(a) yr = x * math.sin(a) + y * math.cos(a) return (xr, z * math.cos(e) - yr * math.sin(e)) def bloch_svg(q: Mapping[str, Any], *, size: int = 150, view: Sequence[float] = VIEW) -> str: """One qubit's Bloch vector on its sphere, seen from ``view``.""" r = size * 0.36 cx, cy = size / 2, size / 2 + 4 az, el = view def pt(v): px, py = project(v, az, el) return cx + r * px, cy - r * py out = [ f'', f'', ] # The equator, as the projection draws it. eq = " ".join(f"{x:.2f},{y:.2f}" for x, y in (pt((math.cos(t), math.sin(t), 0.0)) for t in (2 * math.pi * k / 48 for k in range(49)))) out.append(f'') for v, label in (((0, 0, 1), "|0⟩"), ((0, 0, -1), "|1⟩"), ((1, 0, 0), "+x"), ((0, 1, 0), "+y")): x0, y0 = pt(tuple(-c for c in v)) x1, y1 = pt(v) out.append(f'') lx, ly = pt(tuple(1.22 * c for c in v)) out.append(f'{escape(label)}') tx, ty = pt((q["x"], q["y"], q["z"])) out.append(f'') out.append(f'') out.append(f'q{q["qubit"]}') out.append("") return "".join(out) def bloch_html(data: Mapping[str, Any]) -> str: """Each qubit's sphere and vector, with its components and length.""" cells = [] for q in data.get("qubits") or []: nums = f'x {_num(q["x"])} · y {_num(q["y"])} · z {_num(q["z"])}
length {_num(q["length"])}' cells.append(f'
{bloch_svg(q)}
{nums}
') head = f'
Bloch vectors · {escape(str(data.get("method") or "?"))} · accuracy {escape(str(data.get("accuracy") or "?"))}
' note = f'
Each qubit\'s reduced state: length 1 is pure, shorter is mixed (entangled with the others, or noisy).
' return f'
{head}
{"".join(cells)}
{note}
' def job_html(job: Any) -> str: """A job's card, as the Result widget's data draws it.""" from ._data import result_data return result_html(result_data(job))