notebook-workflow · git:20260526.04c57b9 · 2026-05-26 · sha256 098688f2c8037a20
notebook-workflow git:20260526.04c57b9C
Immutable. This exact content is served forever at /api/v1/blob/098688f2c8037a20.
# Notebook Workflow
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:
```python
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:**
```python
# 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:
```python
# 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:
```python
# 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:
```python
# 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.