Cram sheet — Section 2: Visualize quantum circuits, measurements, and states
One-screen review layer for this section: short background primers per objective, then the key facts — each backed by an official source or by an executed proof from the question bank.
Visualize quantum circuits
Four renderers, and a signature that does not forgive typos
QuantumCircuit.draw() and the standalone circuit_drawer() are the same machinery, and output= accepts exactly four names.
output | Returns | Reach for it when |
|---|---|---|
text (default) | a TextDrawing — printable, but not a str and not None | you are in a terminal or notebook |
mpl | a matplotlib.figure.Figure | you need to style or savefig a publication figure |
latex | a PIL Image, and it needs a LaTeX toolchain | you want typeset output |
latex_source | the raw LaTeX string | you are pasting into a document |
Anything else raises VisualizationError whose message lists those four. The one exception to memorize: pass your own axes with draw("mpl", ax=ax) and the return value is None, because the caller already owns the figure.
| Keyword | Effect | Notes |
|---|---|---|
idle_wires=False | deletes any wire carrying no operations | "auto" keeps them unless the circuit carries a transpiler layout |
reverse_bits=True | draws the highest-index qubit on the top wire | works in every renderer |
initial_state=True | prefixes each wire with its starting label | |
plot_barriers=False | hides barriers | works in every renderer |
filename= | saves the rendering to disk | |
fold, scale, style | wrap width, size, styling | renderer-specific |
The signature is closed — there is no **kwargs catch-all, so a near-miss keyword is a hard TypeError, never a silently ignored option.
Sources: visualize-circuits · visualization
Must know:
- A classically-controlled gate that draws as an
Ifblock is built withwith qc.if_test((qc.clbits[0], 1)):—.c_if(), acondition=kwarg, a.conditionattribute, andif_test(clbit == 1)all fail in Qiskit 2.x. — ⚙️ proven ins2-q013 idle_wires=Falseremoves wires that carry no operations, so a 3-qubit circuit acting only on qubits 0 and 2 draws two wires. — ⚙️ proven ins2-q011
Traps:
output="matplotlib"andoutput="figure"are not valid — both raiseVisualizationErrorlisting the four real names, from the method and fromcircuit_draweralike. — ⚙️ proven ins2-q015- The standalone drawer is
from qiskit.visualization import circuit_drawercalled ascircuit_drawer(qc, output="text");qiskit.toolsno longer exists and the kwarg isoutput=, neverformat=. — ⚙️ proven ins2-q014 qc.draw("mpl", ax=...)returnsNone, not aFigure— supplying your own axes hands figure ownership back to you. — ⚙️ proven ins2-q017reverse_bits=Trueis rendering-only: it puts the highest-index qubit on the top wire and changes nothing about the circuit, the gate order, or the endianness of the results. — ⚙️ proven ins2-q012initial_state=True(defaultFalse) draws the|0⟩labels; the pluralinitial_states=is aTypeError, andstyle={"initial_state": True}is silently ignored by the text renderer. — ⚙️ proven ins2-q016
Visualize quantum measurements
Counts in, Figure out — and the bar labels are little-endian
Both measurement plotters take a counts mapping — bitstring to integer — and return a matplotlib.figure.Figure.
counts = result[0].data.meas.get_counts() # SamplerV2 -> BitArray -> counts
plot_histogram([before, after], legend=["before", "after"])
plot_histogram | plot_distribution | |
|---|---|---|
| plots | raw counts | a normalized quasi-probability distribution |
| y-axis label | Count | Quasi-probability |
| heights add up to | the shot count | 1.0 |
| where normalization comes from | — | the counts themselves |
The display options are a small, memorizable set: legend (a LIST of strings, one per execution), sort ("asc" or "desc"), number_to_keep, color, bar_labels and figsize.
Reading the axis is the last piece. Qiskit labels outcomes little-endian, q_(n−1)…q_1 q_0, with the highest-index qubit on the LEFT. When a circuit has several classical registers — measure_all appends a fresh meas register — the key is space-separated, one group per register, the LAST-declared register printed leftmost.
Sources: visualize-results · visualization
The device plots draw the hardware, not the results
Three device plots draw the same qubit graph and differ only in what they colour.
| Function | Takes | Colours |
|---|---|---|
plot_gate_map(backend) | a BackendV2 | nothing; plot_directed=True adds arrows, not error data |
plot_error_map(backend) | a BackendV2 | every qubit and every link, from calibration data |
plot_circuit_layout(isa, backend) | a transpiled circuit plus its backend | a two-tone used/unused highlight, labelled with virtual indices |
plot_gate_map is a picture of the HARDWARE: it reads the backend's qubit count and coupling map and draws one node per qubit plus one line per connected pair. Reach for this family when the question is about the DEVICE — which qubits exist, how they connect, how good they are, and where the transpiler put your circuit — never about measurement outcomes.
Sources: visualization · visualize-results
Must know:
SamplerV2output must be converted first:result[0].data.meas.get_counts(). TheBitArrayitself is not a counts mapping and has no bare.counts()method. — ⚙️ proven ins2-q022number_to_keep=2on four outcomes draws three bars — the two largest plusrest, whose height is the SUM of the folded counts (20 + 4 → 24), never their average. — ⚙️ proven ins2-q021- Overlaying runs takes a LIST of counts dicts plus a matching list
legend:plot_histogram([before, after], legend=["before", "after"]).labels=does not exist and a bare string legend raises. — ⚙️ proven ins2-q023 plot_circuit_layoutreadscircuit.layout, which only the circuit RETURNED bytranspilecarries —transpilenever mutates its input, so plotting the original raisesQiskitError: 'Circuit has no layout. Perhaps it has not been transpiled.'at every optimization level. — ⚙️ proven ins2-q036Statevector.sample_counts(shots)returns aqiskit.result.Countsmapping summing toshotswith only nonzero-amplitude outcomes, so it feedsplot_histogramwith no backend or primitive involved;sample_memory(shots)is the per-shot list andsv.seed(...)makes the draw reproducible. — ⚙️ proven ins2-q039
Traps:
- Histogram labels are little-endian q_(n−1)…q_0: flipping qubits 0 and 2 of a 3-qubit register puts the single bar at
'101', not'011'. — ⚙️ proven ins2-q019 - Neither plotter has a
shots=parameter —plot_distribution(counts, shots=1024)raisesTypeError; the V1-era habitplot_histogram(counts, shots=1024)is simply gone. — ⚙️ proven ins2-q020 - With no options,
plot_histogramsorts bars in ascending lexicographic bitstring order — not insertion order and not by bar height — and returns aFigure. — ⚙️ proven ins2-q025 plot_gate_mapneeds aBackendV2: a counts mapping, aCouplingMapor aTargetall raiseAttributeError— andplot_histogram(backend)raises too. — ⚙️ proven ins2-q037
Visualize quantum states
Each state plot answers a different question
Pick a state plot by the question it answers; each is a free function, and also a token of sv.draw(output).
| Plot | Draws | Answers |
|---|---|---|
plot_bloch_multivector(state) | one sphere per qubit, from that qubit's reduced state | where each qubit points |
plot_state_qsphere(state) | one node per nonzero amplitude, sized and coloured | which amplitudes exist, and their relative phases |
plot_state_city(state) | two 3-D bar charts, the real and imaginary parts of ρ | individual density-matrix elements |
plot_state_hinton(state) | squares whose size is the magnitude | the same matrix, at a glance |
plot_state_paulivec(state) | the expansion coefficients over Pauli strings | the Pauli decomposition |
plot_bloch_multivector takes a quantum STATE and traces out the other qubits; plot_bloch_vector is the different function that takes an explicit three-number vector [x, y, z].
On sv.draw(output), output is the first positional parameter and the valid tokens are text, latex, latex_source, qsphere, hinton, bloch, city and paulivec. Unlike the other state plots, plot_state_qsphere accepts only figsize, not title.
Sources: plot-quantum-states · visualization
Reading an arrow, reading a node
The Bloch vector is (⟨X⟩, ⟨Y⟩, ⟨Z⟩), so reading an arrow is memorization.
| Arrow | State | How you land there |
|---|---|---|
| +Z (north pole) | the zero state | the starting point |
| −Z (south pole) | the one state | — |
| +X | the plus state | h alone |
| −X | the minus state, the −1 eigenstate of X | — |
| +Y | the 'r' state, a +i relative phase | h then s, a 90° rotation about Z |
| −Y | the 'l' state, a −i relative phase | — |
Anywhere on the equator means ⟨Z⟩ = 0. Because this plot only ever shows single-qubit expectation values, it cannot represent correlations between qubits.
A q-sphere encodes different information: node SIZE is the amplitude magnitude and node COLOUR is its complex phase, so a q-sphere is the plot that shows relative phase between basis states.
Sources: plot-quantum-states
Must know:
plot_bloch_multivectordraws one sphere PER QUBIT (3 qubits → 3 spheres, idle ones included) and packs them all into a single returnedFigure. — ⚙️ proven ins2-q026- For the Bell state both reduced Bloch vectors are exactly (0, 0, 0) with purity 0.5 — the arrows collapse to the centre, the visual signature of maximal entanglement. — ⚙️ proven in
s2-q030 - Two equal-magnitude q-sphere amplitudes of +0.7071 and −0.7071 give same-size nodes at phase 0 and phase π, hence two different colours. — ⚙️ proven in
s2-q032 - A q-sphere shows a node only where the amplitude is nonzero — H on qubit 0 with X on qubit 1 gives nodes at
|10⟩and|11⟩only (little-endian labels). — ⚙️ proven ins2-q031
Traps:
- Passing a quantum state to
plot_bloch_vectordoes not produce per-qubit spheres — that function wants an explicit[x, y, z], and onlyplot_bloch_multivectortakes a state. — ⚙️ proven ins2-q034 sv.draw("qsphere")works, butsv.qsphere(),sv.plot(...)and importingplot_qsphereall fail, and any other draw token raisesValueErrorlisting the valid ones. — ⚙️ proven ins2-q029rz(π/2)on |0⟩ changes only a global phase, so the arrow stays pinned at the north pole, whilehandh; sboth land on the equator. — ⚙️ proven ins2-q035
- Name the four
drawoutputs and the return type of each before choosing one. - Reject any drawing keyword you cannot name — the signature has no
**kwargs, so typos raise. - Convert a
SamplerV2result withresult[0].data.meas.get_counts()before plotting anything. - Read every bitstring right-to-left: the leftmost character is the highest-index qubit.
- Ask whether a plot wants counts, a quantum state, or a backend before picking it.
- Treat Bloch arrows at the origin as the signature of maximal entanglement, not an error.
- Transpile first, then plot a layout — the original circuit carries none.
- Decide what the question needs: per-qubit direction, amplitudes and phases, or matrix elements.
Every fact above is sourced: 📖 links go to official documentation, ⚙️ marks facts observed by executing code against the pinned Qiskit stack (the linked section page shows the proof evidence on its practice questions).