Notebook Workflow

SkillDev tools

How to use LightStim notebooks: from protocol prototyping through packaging, benchmarking, and final demo format.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Notebook Workflow skill

About this capability

A QEC Evaluator built on Stim. Automated DEM construction.

What this skill tells your AI

The instructions your AI receives, as published by qutone/lightstim in skills/notebook-workflow/SKILL.md and read by ahel’s review.

How to use LightStim notebooks: from protocol prototyping through packaging, benchmarking, and final demo format.


1. Development lifecycle

[PROTOTYPE] notebook
      │  implement circuit logic, visualize, debug
      ↓
lightstim/protocols/<name>.py    ← package the protocol
      │
      ↓
benchmarks/<category>/           ← large-scale numerical sweep
      │  run_<name>.py  (CSV output, checkpointing)
      │  plot_<name>.py (reads CSV, saves PNG)
      ↓
[DEMO] notebook                  ← import from protocols, strip raw code

2. Notebook status labels

Add one of these labels at the top of every notebook (as a Markdown cell):

**[PROTOTYPE]** — protocol code lives here; not yet packaged into lightstim/protocols/
**[DEMO]** — protocol is in lightstim/protocols/; this notebook only imports and demonstrates

A DEMO notebook should contain no raw circuit-building logic — only imports, a small visualization, and a small hardcoded numerical result.


3. Verification before packaging

Before moving a protocol from notebook to lightstim/protocols/, validate with a small-scale run (d=3, a handful of p-values):

Pass criteria:

  • LER ≤ 10× PER at the target operating point → circuit is connected, decoding is working
  • LER < PER (breakeven) → ideal, but not required at d=3 (color code needs d≥5)

Fault-tolerant check (applies to memory, gate, distillation):

  • Compare LER at d=3 vs d=5 under the same p
  • FT protocol: d=5 should be ~10× better than d=3
  • Non-FT (e.g., state injection): no distance suppression expected — LER is dominated by injection error probability, not code distance

What to look for if verification fails:

  • LER ≈ 50%: detector or observable wiring error — check tracker output
  • LER ≈ PER (no suppression on FT circuit): noise is not on the right qubits, or boundary stabilizers are missing
  • Huge LER variance: too few shots — increase or use a higher p for smoke test

4. Circuit visualization tricks

Use fewer rounds for readable diagrams

Detslice diagrams with many rounds are hard to read. Use 1–2 SE rounds:

circuit = MyProtocol(d=3, rounds=2).build()
circuit.without_noise().diagram("detslice-with-ops-svg")

This keeps the diagram to 2-3 columns and makes detector connections legible.

Comment out large diagram cells before committing

Inline SVG from .diagram(...) is embedded as a base64 blob in the .ipynb file. A single detslice diagram for d=7 can add 1–3 MB to the file.

Before git add or git commit, comment out or clear output from cells like:

# Comment out before committing:
# circuit.without_noise().diagram("detslice-with-ops-svg")

# Alternatively, clear all outputs with: Kernel → Restart & Clear Output

If you want to keep the visualization result, export it to a PNG/SVG separately and reference it from a Markdown cell instead.

Filter to a subset of detectors or observables

Use filter_coords to isolate a specific stabilizer type or spatial region:

# Show only Z-type detectors (coords where z-component matches)
circuit.without_noise().diagram(
    "detslice-with-ops-svg",
    filter_coords={2: 1},   # example: filter on the 3rd coord = 1
)

This is useful when the full diagram is too dense to read.

Zoom into a specific time segment

Use tick=range(start, end) to show only a slice of the circuit in time:

# Show only the second SE round (ticks 5–10, for example)
circuit.without_noise().diagram(
    "detslice-with-ops-svg",
    tick=range(5, 11),
)

Useful for inspecting the boundary between rounds, or the final measurement.


5. Demo notebook structure

After packaging, a notebook should follow this layout:

# Cell 1: imports
from lightstim.protocols.my_protocol import MyProtocol
from lightstim.simulation.decoder_backend import SimulationPipeline, DecoderConfig
import stim

# Cell 2: circuit visualization (small scale, 1-2 rounds)
circuit = MyProtocol(d=3, rounds=2).build()
# circuit.without_noise().diagram("detslice-with-ops-svg")  # ← commented out before commit

# Cell 3: small numerical result (hardcoded, no sweep loop)
import lightstim.noise.config as nc
noisy = ...  # inject noise
pipeline = SimulationPipeline(DecoderConfig("pymatching"), max_shots=10_000, max_errors=100)
stats = pipeline.run(noisy)
print(f"d=3, p=1e-3: LER = {stats.logical_error_rate:.2e}")

No sweep loops, no CSV output, no argparse. Those belong in benchmarks/.


6. Protocol → notebook mapping

See notebooks/README.md for the full table of notebooks and their corresponding protocols.

Signals

GitHub stars
46
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
notebook-workflow
Source
github.com/qutone/lightstim