Skill Tracer
Skills › Scientific Agent Skills › qiskit › visualization.md

visualization.md

361 lines · skills/qiskit/references/visualization.md at 5f2bc03

Open on GitHub
1# Visualization
2
3Qiskit visualizes circuits, sampled counts, ideal states, and backend layouts. The local Matplotlib/text/Bloch examples were executed; LaTeX, notebook displays, and backend maps are illustrative. Plotting is analysis support, not a substitute for numerical validation.
4

Visualization

Qiskit visualizes circuits, sampled counts, ideal states, and backend layouts. The local Matplotlib/text/Bloch examples were executed; LaTeX, notebook displays, and backend maps are illustrative. Plotting is analysis support, not a substitute for numerical validation.

Raw lines 1 to 4
5## Install Plotting Dependencies
6
7```bash
8uv pip install "qiskit[visualization]==2.5.2"
9```
11The text circuit drawer works with the core package. Matplotlib, Pillow, LaTeX helpers, and notebook integrations depend on the selected output.

Install Plotting Dependencies

uv pip install "qiskit[visualization]==2.5.2"

The text circuit drawer works with the core package. Matplotlib, Pillow, LaTeX helpers, and notebook integrations depend on the selected output.

Raw lines 5 to 12
13## Circuit Drawers

Circuit Drawers

Raw lines 13 to 14
15### Text
17```python
18from qiskit import QuantumCircuit
20circuit = QuantumCircuit(3)
21circuit.h(0)
22circuit.cx(0, 1)
23circuit.cx(1, 2)
25print(circuit.draw(output="text", fold=-1))
26```
28Text output is the most reliable choice for logs, tests, and terminal-only environments.

Text

from qiskit import QuantumCircuit

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

print(circuit.draw(output="text", fold=-1))

Text output is the most reliable choice for logs, tests, and terminal-only environments.

Raw lines 15 to 29
30### Matplotlib
32```python
33figure = circuit.draw(
34 output="mpl",
35 style="iqp",
36 fold=40,
37 idle_wires=False,
39figure.savefig(
40 "circuit.svg",
41 bbox_inches="tight",
43```
45Keep the returned `Figure`; calling `savefig()` on an unrelated current figure can save the wrong plot.
47Useful options:
49```python
50circuit.draw(
51 output="mpl",
52 reverse_bits=False,
53 initial_state=True,
54 plot_barriers=True,
55 fold=30,
57```
59`reverse_bits` changes display order, not circuit semantics.

Matplotlib

figure = circuit.draw(
    output="mpl",
    style="iqp",
    fold=40,
    idle_wires=False,
)
figure.savefig(
    "circuit.svg",
    bbox_inches="tight",
)

Keep the returned Figure; calling savefig() on an unrelated current figure can save the wrong plot.

Useful options:

circuit.draw(
    output="mpl",
    reverse_bits=False,
    initial_state=True,
    plot_barriers=True,
    fold=30,
)

reverse_bits changes display order, not circuit semantics.

Raw lines 30 to 60
61### LaTeX
63```python
64latex_image = circuit.draw(output="latex")
65latex_source = circuit.draw(output="latex_source")
66```
68LaTeX rendering requires an appropriate local TeX installation. Prefer SVG from the Matplotlib drawer when a full TeX toolchain is unavailable.

LaTeX

latex_image = circuit.draw(output="latex")
latex_source = circuit.draw(output="latex_source")

LaTeX rendering requires an appropriate local TeX installation. Prefer SVG from the Matplotlib drawer when a full TeX toolchain is unavailable.

Raw lines 61 to 69
70## Custom Circuit Styles
72```python
73style = {
74 "displaycolor": {
75 "h": ("#648fff", "#ffffff"),
76 "cx": ("#785ef0", "#ffffff"),
77 "measure": ("#dc267f", "#ffffff"),
78 },
79 "fontsize": 11,
80 "subfontsize": 8,
83figure = circuit.draw(output="mpl", style=style)
84```
86Built-in style names can change. `iqp` and `bw` are useful starting points in Qiskit 2.5.
88Use color plus labels or structure; do not make color the only way to distinguish operations.

Custom Circuit Styles

style = {
    "displaycolor": {
        "h": ("#648fff", "#ffffff"),
        "cx": ("#785ef0", "#ffffff"),
        "measure": ("#dc267f", "#ffffff"),
    },
    "fontsize": 11,
    "subfontsize": 8,
}

figure = circuit.draw(output="mpl", style=style)

Built-in style names can change. iqp and bw are useful starting points in Qiskit 2.5.

Use color plus labels or structure; do not make color the only way to distinguish operations.

Raw lines 70 to 89
90## Count Histograms
92```python
93from qiskit.visualization import plot_histogram
95figure = plot_histogram(
96 counts,
97 sort="value_desc",
98 bar_labels=True,
99 title="Bell-state samples",
101figure.savefig(
102 "counts.png",
103 dpi=300,
104 bbox_inches="tight",
106```
108Compare datasets:
110```python
111figure = plot_histogram(
112 [ideal_counts, noisy_counts, hardware_counts],
113 legend=["ideal", "noise model", "hardware"],
114 figsize=(10, 5),
116```
118Normalize explicitly when comparing runs with different shot counts:
120```python
121def normalize_counts(counts):
122 total = sum(counts.values())
123 return {
124 bitstring: count / total
125 for bitstring, count in counts.items()
126 }
127```
129Label whether bars are counts, frequencies, or quasi-probabilities. Sampler V2 returns shot data, not V1 quasi-distributions.

Count Histograms

from qiskit.visualization import plot_histogram

figure = plot_histogram(
    counts,
    sort="value_desc",
    bar_labels=True,
    title="Bell-state samples",
)
figure.savefig(
    "counts.png",
    dpi=300,
    bbox_inches="tight",
)

Compare datasets:

figure = plot_histogram(
    [ideal_counts, noisy_counts, hardware_counts],
    legend=["ideal", "noise model", "hardware"],
    figsize=(10, 5),
)

Normalize explicitly when comparing runs with different shot counts:

def normalize_counts(counts):
    total = sum(counts.values())
    return {
        bitstring: count / total
        for bitstring, count in counts.items()
    }

Label whether bars are counts, frequencies, or quasi-probabilities. Sampler V2 returns shot data, not V1 quasi-distributions.

Raw lines 90 to 130
131## Statevector and Density-Matrix Plots
133Construct ideal states only for circuits without measurements, resets, or unsupported classical control:
135```python
136from qiskit.quantum_info import DensityMatrix, Statevector
138state = Statevector.from_instruction(unitary_circuit)
139density_matrix = DensityMatrix(state)
140```
142Available plotters:
144```python
145from qiskit.visualization import (
146 plot_bloch_multivector,
147 plot_state_city,
148 plot_state_hinton,
149 plot_state_paulivec,
150 plot_state_qsphere,
153plot_bloch_multivector(state)
154plot_state_city(density_matrix)
155plot_state_hinton(density_matrix)
156plot_state_paulivec(density_matrix)
157plot_state_qsphere(state)
158```
160Dense state memory grows exponentially:
162- statevector: \(2^n\) complex amplitudes,
163- density matrix: \(4^n\) complex entries.
165Do not construct a dense state solely to make a plot when the system size is not tractable.

Statevector and Density-Matrix Plots

Construct ideal states only for circuits without measurements, resets, or unsupported classical control:

from qiskit.quantum_info import DensityMatrix, Statevector

state = Statevector.from_instruction(unitary_circuit)
density_matrix = DensityMatrix(state)

Available plotters:

from qiskit.visualization import (
    plot_bloch_multivector,
    plot_state_city,
    plot_state_hinton,
    plot_state_paulivec,
    plot_state_qsphere,
)

plot_bloch_multivector(state)
plot_state_city(density_matrix)
plot_state_hinton(density_matrix)
plot_state_paulivec(density_matrix)
plot_state_qsphere(state)

Dense state memory grows exponentially:

  • statevector: \(2^n\) complex amplitudes,
  • density matrix: \(4^n\) complex entries.

Do not construct a dense state solely to make a plot when the system size is not tractable.

Raw lines 131 to 166
167## Single Bloch Vector
169```python
170from qiskit.quantum_info import Pauli, Statevector
171from qiskit.visualization import plot_bloch_vector
173state = Statevector.from_label("+")
174figure = plot_bloch_vector(
175 [float(state.expectation_value(Pauli(axis)).real) for axis in "XYZ"],
176 title="|+>",
178```
180A reduced qubit from an entangled state may be mixed and appear inside the Bloch sphere. A per-qubit Bloch view does not show multipartite entanglement.

Single Bloch Vector

from qiskit.quantum_info import Pauli, Statevector
from qiskit.visualization import plot_bloch_vector

state = Statevector.from_label("+")
figure = plot_bloch_vector(
    [float(state.expectation_value(Pauli(axis)).real) for axis in "XYZ"],
    title="|+>",
)

A reduced qubit from an entangled state may be mixed and appear inside the Bloch sphere. A per-qubit Bloch view does not show multipartite entanglement.

Raw lines 167 to 181
182## Backend Topology and Errors
184```python
185from qiskit.visualization import plot_error_map, plot_gate_map
187gate_map_figure = plot_gate_map(backend)
188error_map_figure = plot_error_map(backend)
189```
191These plots reflect the backend snapshot exposed by the provider. Record the retrieval time and backend.
193Plot a compiled circuit's physical placement:
195```python
196from qiskit.visualization import plot_circuit_layout
198layout_figure = plot_circuit_layout(
199 isa_circuit,
200 backend,
202```
204Use `isa_circuit.layout` for program logic. A plot is for inspection, not a machine-readable mapping.

Backend Topology and Errors

from qiskit.visualization import plot_error_map, plot_gate_map

gate_map_figure = plot_gate_map(backend)
error_map_figure = plot_error_map(backend)

These plots reflect the backend snapshot exposed by the provider. Record the retrieval time and backend.

Plot a compiled circuit's physical placement:

from qiskit.visualization import plot_circuit_layout

layout_figure = plot_circuit_layout(
    isa_circuit,
    backend,
)

Use isa_circuit.layout for program logic. A plot is for inspection, not a machine-readable mapping.

Raw lines 182 to 205
206## Before-and-After Circuit Comparison
208```python
209import matplotlib.pyplot as plt
211figure, axes = plt.subplots(
212 nrows=2,
213 figsize=(14, 7),
214 constrained_layout=True,
217circuit.draw(
218 output="mpl",
219 ax=axes[0],
220 fold=-1,
222axes[0].set_title("Logical circuit")
224isa_circuit.draw(
225 output="mpl",
226 ax=axes[1],
227 fold=-1,
229axes[1].set_title(
230 f"ISA circuit on {backend.name}"
233figure.savefig(
234 "logical-vs-isa.svg",
235 bbox_inches="tight",
237```
239For very wide circuits, save separate figures rather than shrinking labels until unreadable.

Before-and-After Circuit Comparison

import matplotlib.pyplot as plt

figure, axes = plt.subplots(
    nrows=2,
    figsize=(14, 7),
    constrained_layout=True,
)

circuit.draw(
    output="mpl",
    ax=axes[0],
    fold=-1,
)
axes[0].set_title("Logical circuit")

isa_circuit.draw(
    output="mpl",
    ax=axes[1],
    fold=-1,
)
axes[1].set_title(
    f"ISA circuit on {backend.name}"
)

figure.savefig(
    "logical-vs-isa.svg",
    bbox_inches="tight",
)

For very wide circuits, save separate figures rather than shrinking labels until unreadable.

Raw lines 206 to 240
241## Parameter and Convergence Plots
243Qiskit returns numerical arrays; use Matplotlib directly for scientific plots:
245```python
246import matplotlib.pyplot as plt
248figure, axis = plt.subplots()
249axis.plot(iterations, objective_values, marker="o")
250axis.set(
251 xlabel="Objective evaluation",
252 ylabel="Energy (hartree)",
253 title="VQE convergence",
255axis.grid(alpha=0.25)
256figure.savefig(
257 "vqe-convergence.svg",
258 bbox_inches="tight",
260```
262Include uncertainty bars when repeated runs or estimator standard deviations are available:
264```python
265axis.errorbar(
266 parameter_values,
267 expectation_values,
268 yerr=standard_deviations,
269 fmt="o-",
270 capsize=3,
272```
274Do not interpret optimizer history as statistically independent samples.

Parameter and Convergence Plots

Qiskit returns numerical arrays; use Matplotlib directly for scientific plots:

import matplotlib.pyplot as plt

figure, axis = plt.subplots()
axis.plot(iterations, objective_values, marker="o")
axis.set(
    xlabel="Objective evaluation",
    ylabel="Energy (hartree)",
    title="VQE convergence",
)
axis.grid(alpha=0.25)
figure.savefig(
    "vqe-convergence.svg",
    bbox_inches="tight",
)

Include uncertainty bars when repeated runs or estimator standard deviations are available:

axis.errorbar(
    parameter_values,
    expectation_values,
    yerr=standard_deviations,
    fmt="o-",
    capsize=3,
)

Do not interpret optimizer history as statistically independent samples.

Raw lines 241 to 275
276## Publication Output
278Prefer vector formats for circuit diagrams and line art:
280```python
281figure.savefig(
282 "figure.svg",
283 bbox_inches="tight",
284 metadata={"Creator": "Qiskit 2.5 workflow"},
286figure.savefig(
287 "figure.pdf",
288 bbox_inches="tight",
290```
292For raster output:
294```python
295figure.savefig(
296 "figure.png",
297 dpi=300,
298 bbox_inches="tight",
300```
302Include in the caption:
304- logical or transpiled status,
305- backend if transpiled,
306- measurement basis,
307- shot count or precision,
308- mitigation configuration,
309- whether data are ideal, modeled, or hardware-derived.

Publication Output

Prefer vector formats for circuit diagrams and line art:

figure.savefig(
    "figure.svg",
    bbox_inches="tight",
    metadata={"Creator": "Qiskit 2.5 workflow"},
)
figure.savefig(
    "figure.pdf",
    bbox_inches="tight",
)

For raster output:

figure.savefig(
    "figure.png",
    dpi=300,
    bbox_inches="tight",
)

Include in the caption:

  • logical or transpiled status,
  • backend if transpiled,
  • measurement basis,
  • shot count or precision,
  • mitigation configuration,
  • whether data are ideal, modeled, or hardware-derived.
Raw lines 276 to 310
311## Removed Visualization Patterns
313Do not use:
315- `qiskit.tools.jupyter.QuantumCircuitComposer` from old examples,
316- pulse schedule drawings based on `qiskit.pulse`,
317- nonexistent `plot_state_density` helpers,
318- V1 quasi-distribution examples presented as Sampler V2 output.
320`qiskit.pulse` was removed in Qiskit 2.0. Use fractional-gate documentation for IBM hardware. Qiskit Dynamics is archived; do not treat it as a maintained replacement for new control-model research.

Removed Visualization Patterns

Do not use:

  • qiskit.tools.jupyter.QuantumCircuitComposer from old examples,
  • pulse schedule drawings based on qiskit.pulse,
  • nonexistent plot_state_density helpers,
  • V1 quasi-distribution examples presented as Sampler V2 output.

qiskit.pulse was removed in Qiskit 2.0. Use fractional-gate documentation for IBM hardware. Qiskit Dynamics is archived; do not treat it as a maintained replacement for new control-model research.

Raw lines 311 to 321
322## Troubleshooting

Troubleshooting

Raw lines 322 to 323
324### Matplotlib output is unavailable
326Install the pinned visualization extra and verify the active interpreter:
328```bash
329uv pip install "qiskit[visualization]==2.5.2"
330python -c "import sys, matplotlib; print(sys.executable, matplotlib.__version__)"
331```

Matplotlib output is unavailable

Install the pinned visualization extra and verify the active interpreter:

uv pip install "qiskit[visualization]==2.5.2"
python -c "import sys, matplotlib; print(sys.executable, matplotlib.__version__)"
Raw lines 324 to 332
333### Notebook displays nothing
335Return the `Figure` as the final expression or call:
337```python
338import matplotlib.pyplot as plt
340plt.show()
341```

Notebook displays nothing

Return the Figure as the final expression or call:

import matplotlib.pyplot as plt

plt.show()
Raw lines 333 to 342
343### LaTeX drawer fails
345Use `output="mpl"` or `output="text"` unless a complete TeX toolchain is intentionally installed.

LaTeX drawer fails

Use output="mpl" or output="text" unless a complete TeX toolchain is intentionally installed.

Raw lines 343 to 346
347### Count labels look reversed
349Qiskit prints count strings with the highest-index classical bit on the left. Convert explicitly before mapping characters to qubit-indexed variables.

Count labels look reversed

Qiskit prints count strings with the highest-index classical bit on the left. Convert explicitly before mapping characters to qubit-indexed variables.

Raw lines 347 to 350
351### Backend plot fails
353Confirm the object is a compatible `BackendV2` and that the visualization extra is installed. Some third-party backends do not provide every field expected by IBM-oriented plotting functions.

Backend plot fails

Confirm the object is a compatible BackendV2 and that the visualization extra is installed. Some third-party backends do not provide every field expected by IBM-oriented plotting functions.

Raw lines 351 to 354
355### Plot is too large
357- set `fold`,
358- hide idle wires,
359- split logical modules,
360- export to SVG,
361- include structural metrics in text rather than forcing every instruction into one figure.

Plot is too large

  • set fold,
  • hide idle wires,
  • split logical modules,
  • export to SVG,
  • include structural metrics in text rather than forcing every instruction into one figure.
Raw lines 355 to 361