Skip to content

QEC Studio

QEC Studio is Research mode’s quantum-error-correction workflow. It turns a Stim stabilizer circuit into a set of visualizations no other desktop tool has, then sweeps it over noise to measure how well the code protects logical information.

The fastest way in is Experiments → New QEC experiment. Pick Repetition code memory or Rotated surface code memory and Nuclei writes two real, editable files into your project:

  • qec/<name>.py — a Stim-generating entry defining nuclei_circuits(noise) -> dict[str, stim.Circuit]. Nothing is hidden; open it and change the distances, the code task, or build circuits by hand.
  • experiments/<name>.experiment.yaml — a qec_campaign spec pointing at that entry. See Campaigns for every field.

The entry labels its circuits d=3, d=5, d=7; that convention is what lets the threshold panel fit Λ across distances.

Open a .stim file (or run Stim-building Python) and the visualization zone swaps its Bloch sphere for three QEC panels:

  • Timeline — the circuit moment by moment: resets, gates, measurements, and detector/observable annotations per tick.
  • Code Lattice — data and measure qubits laid out from the circuit’s qubit coordinates (generated codes include them; hand-built circuits may not, and the panel says so).
  • Detector Graph — the circuit’s detector error model (DEM) drawn as a graph: detector nodes placed by their coordinates, edges between the detectors each error mechanism flips, and boundary edges to a virtual node. It’s the panel no other desktop tool has — and where you decode. It gets its own two sections below.

The detector graph renders on a canvas, so it stays smooth from a distance-3 code up to the tens of thousands of edges of a large surface code. The drawing is information-dense on purpose:

  • Edges are heat-coloured and weighted by error probability — faint slate for rare mechanisms, through teal, to a warm glow for the likeliest ones. A code’s fragile “hotspots” are visible at a glance instead of a uniform mesh.
  • Boundary edges (to the virtual boundary node) are dashed; edges that flip a logical observable carry a bright accent, since they move logical information you can’t afford to mis-correct.
  • Hover a detector to inspect it — its index, how many edges touch it, and whether it has fired. A legend in the corner spells out the encoding.

Very large graphs are still capped for the initial payload, but nothing is lost: the banner reports the true edge counts and a Render full graph button parses the complete model in the app — a WebAssembly parser runs over the DEM text the kernel forwards — and draws it with no edge limit. A circuit with no valid DEM shows the reason, not a blank box.

The detector graph is where you watch a decoder work. There are two modes, for two different questions.

Press Sample a shot and the kernel runs one Monte-Carlo shot through the real decoder (PyMatching): the fired detectors light up, the decoder’s matching is drawn on top, and you get an honest “logical error this shot” / “corrected” verdict. This is the same decoder a campaign uses — the numbers you’d trust.

Toggle Interactive and the graph becomes a sandbox: click detectors to build any syndrome you like, and a decoder re-solves the matching instantly, in the app, with no kernel round-trip. The correction lights up as you click, with a live readout of whether it crosses a logical observable. It’s for building intuition — “what would the decoder do with this syndrome, and would it be a logical error?” — not for publishable numbers.

With a qec_campaign experiment selected, the analysis view gives you a Run campaign button and a live progress chip (tasks complete / shots sampled). A campaign is a set of Stim tasks — labels × noise points × decoders — sampled by sinter across worker processes.

Quit mid-campaign and the next run resumes without re-sampling: the stats already collected are handed back to sinter as a starting point. Campaigns are Monte-Carlo and not seed-reproducible — sinter has no seeding API, and Nuclei doesn’t pretend otherwise.

Results stream into the Threshold / Λ panel: logical error rate per shot vs the physical error parameter, on log-log axes, one series per (label × distance × decoder), with Wilson confidence intervals. Below threshold, higher distances sit lower and the curves fan out; the panel reports the fitted Λ (the error-suppression factor between successive distances, Λ > 1 = below threshold) and a projected distance to reach a target logical error rate.

The Resource Estimator panel answers the next question: given a Q# or Qiskit algorithm, how many physical qubits and how much wall-clock time would a fault-tolerant implementation actually need?