Skip to main content

Backend-agnostic quantum circuit drawing library with Matplotlib as the first renderer.

Project description

Quantum Circuit Drawer logo

quantum-circuit-drawer

quantum-circuit-drawer is a Matplotlib-based library for drawing quantum circuits, plotting measurement results, and comparing outputs across several quantum ecosystems with one consistent public API.

The main idea is simple:

  • build your circuit or result object the way you normally would
  • call one public function
  • get a stable result object back

What You Can Do

The library is centered on four user workflows:

Workflow Public API Typical use
Draw one circuit draw_quantum_circuit(...) Render a Qiskit, Cirq, PennyLane, MyQLM, CUDA-Q, or IR circuit
Compare two circuits compare_circuits(...) Show before/after structure, for example before and after transpilation
Plot one result distribution plot_histogram(...) Plot counts, quasi-probabilities, marginals, or framework-native result objects
Compare two result distributions compare_histograms(...) Overlay ideal vs sampled, baseline vs new run, or counts vs quasi

The public configuration is also intentionally small:

  • DrawConfig for circuit rendering
  • HistogramConfig for single histograms
  • CircuitCompareConfig for side-by-side circuit comparison
  • HistogramCompareConfig for histogram comparison

Each public config is now grouped into typed blocks ordered by responsibility:

  • circuit drawing uses DrawConfig(side=..., output=...)
  • circuit comparison uses CircuitCompareConfig(shared=..., compare=..., output=...)
  • single histograms use HistogramConfig(data=..., view=..., appearance=..., output=...)
  • histogram comparison uses HistogramCompareConfig(data=..., compare=..., output=...)

Install

Inside your local .venv:

Windows PowerShell:

.\.venv\Scripts\python.exe -m pip install quantum-circuit-drawer

Linux or WSL:

.venv/bin/python -m pip install quantum-circuit-drawer

Install only the extras you need:

Windows PowerShell:

.\.venv\Scripts\python.exe -m pip install "quantum-circuit-drawer[qiskit]"
.\.venv\Scripts\python.exe -m pip install "quantum-circuit-drawer[cirq]"
.\.venv\Scripts\python.exe -m pip install "quantum-circuit-drawer[pennylane]"
.\.venv\Scripts\python.exe -m pip install "quantum-circuit-drawer[myqlm]"

Linux or WSL:

.venv/bin/python -m pip install "quantum-circuit-drawer[qiskit]"
.venv/bin/python -m pip install "quantum-circuit-drawer[cirq]"
.venv/bin/python -m pip install "quantum-circuit-drawer[pennylane]"
.venv/bin/python -m pip install "quantum-circuit-drawer[myqlm]"

CUDA-Q remains a Linux or WSL2 path:

.venv/bin/python -m pip install "quantum-circuit-drawer[cudaq]"

Support matrix

This is the production support contract for the current release.

Input path Support level Platform notes
Internal IR Strong support Core built-in path on Windows and Linux
Qiskit Strong support Primary external backend on Windows and Linux
Cirq Best-effort on native Windows Prefer Linux or WSL for the most reliable repeated runs
PennyLane Best-effort on native Windows Prefer Linux or WSL for the most reliable repeated runs
MyQLM Scoped adapter + contract support Adapter contract is covered, but it is not a first-class multiplatform CI backend
CUDA-Q Linux/WSL2 only Not intended for native Windows installs

Choose Your First Task

If you want to... Start here
Draw a circuit from a supported framework Draw one circuit
Save a render from a script without opening a window Save directly to a file
Plot counts or probabilities Plot one histogram
Compare two versions of a circuit Compare two circuits
Compare two distributions Compare two histograms
Build a circuit without a framework dependency Build with public IR tools
Explore framework-specific demos Recommended demos

Draw One Circuit

from qiskit import QuantumCircuit

from quantum_circuit_drawer import DrawConfig, OutputOptions, draw_quantum_circuit

circuit = QuantumCircuit(2, 1)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure(1, 0)

result = draw_quantum_circuit(
    circuit,
    config=DrawConfig(output=OutputOptions(show=False)),
)

figure = result.primary_figure
axes = result.primary_axes

This same shape works for the supported framework objects and for the public IR types.

Save Directly To A File

from qiskit import QuantumCircuit

from quantum_circuit_drawer import DrawConfig, OutputOptions, draw_quantum_circuit

circuit = QuantumCircuit(2, 1)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure(1, 0)

draw_quantum_circuit(
    circuit,
    config=DrawConfig(output=OutputOptions(output_path="bell.png", show=False)),
)

This is the most common script workflow when you want a deterministic export without opening a GUI window.

Plot One Histogram

Counts

from quantum_circuit_drawer import (
    HistogramAppearanceOptions,
    HistogramConfig,
    HistogramDataOptions,
    HistogramViewOptions,
    OutputOptions,
    plot_histogram,
)

result = plot_histogram(
    {"000": 51, "001": 14, "010": 9, "111": 49},
    config=HistogramConfig(
        data=HistogramDataOptions(top_k=3),
        view=HistogramViewOptions(sort="value_desc"),
        appearance=HistogramAppearanceOptions(show_uniform_reference=True),
        output=OutputOptions(show=False),
    ),
)

Quasi-probabilities

from quantum_circuit_drawer import (
    HistogramAppearanceOptions,
    HistogramConfig,
    HistogramDataOptions,
    HistogramKind,
    OutputOptions,
    plot_histogram,
)

result = plot_histogram(
    {0: 0.52, 3: -0.08, 4: 0.17, 7: 0.39},
    config=HistogramConfig(
        data=HistogramDataOptions(kind=HistogramKind.QUASI),
        appearance=HistogramAppearanceOptions(
            draw_style="soft",
            show_uniform_reference=True,
        ),
        output=OutputOptions(show=False),
    ),
)

Joint marginal on selected qubits

from quantum_circuit_drawer import HistogramConfig, HistogramDataOptions, OutputOptions, plot_histogram

result = plot_histogram(
    {"101": 2, "001": 1, "111": 3},
    config=HistogramConfig(
        data=HistogramDataOptions(qubits=(0, 2)),
        output=OutputOptions(show=False),
    ),
)

qubits=(0, 2) keeps the requested order, so the marginal labels are built as q0 followed by q2.

Compare Two Circuits

from qiskit import QuantumCircuit, transpile

from quantum_circuit_drawer import (
    CircuitCompareConfig,
    CircuitCompareOptions,
    OutputOptions,
    compare_circuits,
)

source = QuantumCircuit(3, 3)
source.h(0)
source.cx(0, 1)
source.cx(1, 2)
source.measure(range(3), range(3))

transpiled = transpile(source, basis_gates=["u", "cx"], optimization_level=2)

result = compare_circuits(
    source,
    transpiled,
    config=CircuitCompareConfig(
        compare=CircuitCompareOptions(
            left_title="Original",
            right_title="Transpiled",
        ),
        output=OutputOptions(show=False),
    ),
)

CircuitCompareResult gives you:

  • one comparison figure
  • one DrawResult per side
  • structural metrics such as operation counts, measurement counts, swap counts, and differing layers

Compare Two Histograms

from quantum_circuit_drawer import (
    HistogramCompareConfig,
    HistogramCompareOptions,
    OutputOptions,
    compare_histograms,
)

ideal = {"00": 0.5, "11": 0.5}
sampled = {"00": 473, "01": 19, "10": 24, "11": 484}

result = compare_histograms(
    ideal,
    sampled,
    config=HistogramCompareConfig(
        compare=HistogramCompareOptions(
            sort="delta_desc",
            left_label="Ideal",
            right_label="Sampled",
        ),
        output=OutputOptions(show=False),
    ),
)

This is useful when you want one aligned state space and quick metrics such as total variation distance.

Build With Public IR Tools

If you do not want to depend on a framework, you can build directly with the public IR tools or use CircuitBuilder.

CircuitBuilder

from quantum_circuit_drawer import CircuitBuilder, DrawConfig, OutputOptions, draw_quantum_circuit

circuit = (
    CircuitBuilder(2, 1, name="builder_demo")
    .h(0)
    .cx(0, 1)
    .measure(1, 0)
    .build()
)

draw_quantum_circuit(circuit, config=DrawConfig(output=OutputOptions(show=False)))

Raw CircuitIR

If you need complete control over wires, operations, and metadata, use the public quantum_circuit_drawer.ir types directly. The best minimal example for that path is the bundled ir-basic-workflow demo.

Modes, Hover, And 3D

The most common choices are:

  • DrawMode.AUTO: notebook -> pages, normal script -> pages_controls
  • DrawMode.PAGES: easiest for notebook display and export-oriented flows
  • DrawMode.PAGES_CONTROLS: best default for normal scripts
  • DrawMode.SLIDER: best when you want a viewport through a wide circuit
  • DrawMode.FULL: best when the circuit fits comfortably in one scene

Example:

from quantum_circuit_drawer import (
    CircuitAppearanceOptions,
    CircuitRenderOptions,
    DrawConfig,
    DrawMode,
    DrawSideConfig,
    OutputOptions,
    draw_quantum_circuit,
)

result = draw_quantum_circuit(
    circuit,
    config=DrawConfig(
        side=DrawSideConfig(
            render=CircuitRenderOptions(mode=DrawMode.PAGES_CONTROLS),
            appearance=CircuitAppearanceOptions(
                hover={"enabled": True, "show_size": True},
            ),
        ),
        output=OutputOptions(show=False),
    ),
)

For 3D:

from quantum_circuit_drawer import (
    CircuitRenderOptions,
    DrawConfig,
    DrawMode,
    DrawSideConfig,
    OutputOptions,
    draw_quantum_circuit,
)

result = draw_quantum_circuit(
    circuit,
    config=DrawConfig(
        side=DrawSideConfig(
            render=CircuitRenderOptions(
                view="3d",
                mode=DrawMode.PAGES_CONTROLS,
                topology="grid",
                topology_menu=True,
            ),
        ),
        output=OutputOptions(show=False),
    ),
)

If you want to see the managed 2D controls intentionally exercised instead of configuring them from scratch, start with qiskit-2d-exploration-showcase.

Recommended Demos

The fastest way to see the current strengths of the library is to run one of the bundled showcase demos:

Demo id What it highlights
qiskit-2d-exploration-showcase Managed 2D exploration with Wires: All/Active, Ancillas: Show/Hide, folded-wire markers, and contextual Collapse / Expand
qiskit-control-flow-showcase Compact Qiskit control-flow boxes plus open controls
qiskit-composite-modes-showcase Compact versus expanded composite instructions on the same workflow
ir-basic-workflow Framework-free rendering from the public CircuitIR types
cirq-native-controls-showcase Cirq native controls, classical conditions, and CircuitOperation provenance
pennylane-terminal-outputs-showcase PennyLane mid-measurement, qml.cond(...), plus terminal output boxes
myqlm-structural-showcase Compact composite routines on the native MyQLM adapter path
cudaq-kernel-showcase The supported closed-kernel CUDA-Q subset with reset and basis measurements
compare-histograms-ideal-vs-sampled A lightweight comparison workflow with no framework extra required

Windows PowerShell:

.\.venv\Scripts\python.exe examples\qiskit_2d_exploration_showcase.py
.\.venv\Scripts\python.exe examples\qiskit_control_flow_showcase.py
.\.venv\Scripts\python.exe examples\qiskit_composite_modes_showcase.py --composite-mode expand
.\.venv\Scripts\python.exe examples\ir_basic_workflow.py
.\.venv\Scripts\python.exe examples\compare_histograms_ideal_vs_sampled.py

Linux or WSL:

.venv/bin/python examples/qiskit_2d_exploration_showcase.py
.venv/bin/python examples/qiskit_control_flow_showcase.py
.venv/bin/python examples/qiskit_composite_modes_showcase.py --composite-mode expand
.venv/bin/python examples/ir_basic_workflow.py
.venv/bin/python examples/compare_histograms_ideal_vs_sampled.py

The full curated catalog, including direct script commands, histogram demos, compare demos, and per-framework recommendations, lives in examples/README.md.

Documentation

Use these pages depending on what you need:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quantum_circuit_drawer-0.4.0.tar.gz (218.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

quantum_circuit_drawer-0.4.0-py3-none-any.whl (286.2 kB view details)

Uploaded Python 3

File details

Details for the file quantum_circuit_drawer-0.4.0.tar.gz.

File metadata

  • Download URL: quantum_circuit_drawer-0.4.0.tar.gz
  • Upload date:
  • Size: 218.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for quantum_circuit_drawer-0.4.0.tar.gz
Algorithm Hash digest
SHA256 91daf7ded7f071b3fb14b9c749f0eb9fed889fd82c3fed9721c399cbc29d5b4c
MD5 2de6b932e66972131576e21dbe7f9086
BLAKE2b-256 83053e68390beed29e395c64775451481f31408a16ccf7c091466ef9bb91a3f2

See more details on using hashes here.

File details

Details for the file quantum_circuit_drawer-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for quantum_circuit_drawer-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b775ab69f0562d6e2e98e1b15955861081e093d14c64c5b936af1927726fd2d
MD5 59f19af1414d425560c246303052fa42
BLAKE2b-256 7623621bf603b27ace151c5aa7847873a629b9ec1f4d4310b36ce386cd733a8c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page