This is a Typst package for visualizing quantum error correction codes.
Note: Requires CeTZ version >= 0.4.0 and compiler version >= 0.13
steane-code(...) now follows the lightweight object-style API too: construct the figure, call code.draw-background(), then attach labels with code.qubit-anchor(id). Steane qubit ids stay simple integer labels 1 through 7.
#import "@preview/qec-thrust:0.2.0": *
#canvas({
import draw: *
let code = steane-code((0, 0), size: 3)
(code.draw-background)()
for j in range(7) {
content((rel: (0, -0.3), to: (code.qubit-anchor)(j + 1)), [#(j)])
}
})surface-code(...) now returns a reusable object API. Build the object first, call code.draw-background(), then annotate through stable helpers.
code.qubits: qubit records with stable ids(i, j).code.qubit-anchor(id): anchor helper for downstream labels.code.highlight-qubit(id, ...): highlight a single surface qubit.type-tag: falsestill flips the boundary orientation, andpoint-radius/boundary-bulgestill control the geometry.
Here is an example of two surface codes:
#canvas({
import draw: *
let n = 3
let code1 = surface-code((0, 0), n, n, size: 1.5, name: "surface1")
(code1.draw-background)()
for i in range(n) {
for j in range(n) {
content((rel: (0.3, 0.3), to: (code1.qubit-anchor)((i, j))), [#(i*n+j+1)])
}
}
let code2 = surface-code((4, 0), 15, 7, color1: red, color2: green, size: 0.5, type-tag: false)
(code2.draw-background)()
})toric-code(...) now returns a reusable object API. Build the object first, call code.draw-background(), then annotate through stable helpers.
code.qubits: qubit records with stable ids("vertical", i, j)and("horizontal", i, j).code.plaquettes: plaquette stabilizer records with stable zero-based cell ids("plaquette", i, j).code.vertices: vertex stabilizer records with stable zero-based vertex ids("vertex", i, j).code.qubit-anchor(id),code.plaquette-anchor(id),code.vertex-anchor(id): anchor helpers.code.highlight-qubit(id, ...),code.highlight-plaquette(id, ...),code.highlight-vertex(id, ...): stabilizer/qubit emphasis helpers.code.highlight-plaquette(..., selected-qubits: (...))andcode.highlight-vertex(..., selected-qubits: (...)): override the default support when you want to draw custom BB-code-style operators.
Here is a 5x3 toric example:
#canvas({
import draw: *
let m = 5
let n = 3
let size = 2
let circle-radius = 0.4
let code = toric-code((0, 0), m, n, size: size, circle-radius: circle-radius)
(code.draw-background)()
(code.highlight-plaquette)((1, 0))
(code.highlight-vertex)((3, 2))
stabilizer-label((12, -2))
for i in range(m){
for j in range(n){
content((code.qubit-anchor)(("vertical", i, j)), [#(i*n+j+1)])
content((code.qubit-anchor)(("horizontal", i, j)), [#(i*n+j+1+m*n)])
}
}
})Here is the
#canvas({
import draw: *
let code = toric-code((0, 0), 7, 7, size: 1)
(code.draw-background)()
(code.highlight-plaquette)(
(1, 4),
selected-qubits: (
("vertical", 1, 4),
("vertical", 1, 5),
("horizontal", 2, 4),
("horizontal", 1, 4),
("vertical", 4, 5),
("vertical", 5, 5),
("horizontal", 1, 0),
("horizontal", 1, 1),
),
)
(code.highlight-vertex)(
(6, 1),
selected-qubits: (
("vertical", 5, 1),
("vertical", 6, 1),
("horizontal", 6, 1),
("horizontal", 6, 0),
("vertical", 6, 5),
("vertical", 6, 4),
("horizontal", 2, 0),
("horizontal", 3, 0),
),
)
stabilizer-label((10, -3))
})color-code-2d now returns a geometry object instead of drawing directly. This is a breaking change in 0.2.x: construct the patch first, then draw and annotate it explicitly inside canvas.
#canvas({
import draw: *
let code = color-code-2d(
(0, 0),
tiling: "6.6.6",
shape: "rect",
size: (rows: 4, cols: 4),
hex-orientation: "flat",
scale: 1.0,
color1: yellow,
color2: aqua,
color3: olive,
name: "color-rect",
show-qubits: true,
qubit-radius: 0.08,
)
(code.draw-background)()
(code.highlight-face)((0, 0), stroke: (paint: red, thickness: 1pt))
(code.highlight-qubit)((2, 0), stroke: (paint: blue, thickness: 1pt))
content((code.face-anchor)((0, 0)), [f])
content((code.qubit-anchor)((2, 0)), [q])
})The returned object exposes:
code.faces: canonical face records withid,kind,color,center,vertices,qubits, andmeta.code.qubits: canonical qubit records withid,pos,incident-faces,boundary-tags, andmeta.code.boundaries: boundary-indexed qubit ids. For6.6.6hex patches this includesx+,y+,z+,x-,y-, andz-.code.basis: lattice basis information.4.8.8and4.6.12exposeorigin,x, andy;6.6.6exposes orientation metadata.code.face-anchor(id)andcode.qubit-anchor(id): stable anchors for downstream figure composition.code.draw-background(),code.highlight-face(id, ..style), andcode.highlight-qubit(id, ..style): the small official drawing helper surface.
For tiling: "6.6.6", supported shapes are rect, para, tri, tri-cut, and hex. hex-orientation can be "flat" or "pointy" for the non-hex patches (tri-cut requires "flat"). Tuple shorthand such as (0, 0) for faces and (2, 0) for qubits is accepted for the simple 6.6.6 and 4.8.8 id schemes.
The bundled examples/color_code_666.typ now shows the supported 6.6.6 boundary shapes and orientations without annotations, while examples/color_code_666_panels.typ composes the object API into a four-panel figure with basis, stabilizer, anyon, and label views.
tiling: "4.8.8" now uses the same object API, keeps size: (rows: ..., cols: ...) as a rectangular patch boundary, and exposes a geometry-derived 45-degree reading frame through code.basis.origin, code.basis.x, and code.basis.y.
#canvas({
let code = color-code-2d(
(0, 0),
tiling: "4.8.8",
shape: "rect",
size: (rows: 4, cols: 4),
scale: 0.8,
color1: yellow,
color2: aqua,
color3: olive,
name: "color-488",
show-qubits: true,
qubit-radius: 0.1,
)
(code.draw-background)()
})The bundled examples/color_code_488.typ now shows the same rectangular 4.8.8 patch under several viewing rotations, and examples/color_code_488_panels.typ composes the basis, stabilizer, anyon, and label panels on one canvas.
tiling: "4.6.12" also returns the shared object shape. Currently only shape: "rect" is implemented. Stable face ids use the canonical prefixes f-dod-*, f-sq-*, and f-hex-*.
#canvas({
import draw: content
let code = color-code-2d(
(0, 0),
tiling: "4.6.12",
shape: "rect",
size: (rows: 6, cols: 6),
scale: 0.6,
color1: yellow,
color2: aqua,
color3: olive,
name: "color-4612",
show-qubits: true,
qubit-radius: 0.2,
)
(code.draw-background)()
(code.highlight-face)("dod-2-2", stroke: (paint: red, thickness: 1pt))
content((code.face-anchor)("dod-2-2"), [dod])
})- If you draw multiple codes of the same type in one canvas, set a unique
nameprefix to avoid anchor collisions. show-qubits,qubit-radius,qubit-color,show-stabilizers, andstabilizer-offsetare constructor options that affectcode.draw-background().surface-codeuses +y upward, whiletoric-codeuses -y downward (grid grows down).
Licensed under the MIT License.








