Skip to main content

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.

outputReturnsReach for it when
text (default)a TextDrawing — printable, but not a str and not Noneyou are in a terminal or notebook
mpla matplotlib.figure.Figureyou need to style or savefig a publication figure
latexa PIL Image, and it needs a LaTeX toolchainyou want typeset output
latex_sourcethe raw LaTeX stringyou are pasting into a document

Anything else raises VisualizationError whose message lists those four. The one exception: with your own axes, draw("mpl", ax=ax) returns None, because the caller already owns the figure.

KeywordEffectNotes
idle_wires=Falsedeletes any wire carrying no operations — 3 qubits with gates only on 0 and 2 draw two wires"auto" keeps them unless the circuit carries a transpiler layout
reverse_bits=Truedraws the highest-index qubit on the top wireworks in every renderer
initial_state=Trueprefixes each wire with its starting label
plot_barriers=Falsehides barriersworks in every renderer
filename=saves the rendering to disk
fold, scale, stylewrap width, size, stylingrenderer-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 drawn as an If block is built with with qc.if_test((qc.clbits[0], 1)): — .c_if(), a condition= kwarg, a .condition attribute and if_test(clbit == 1) all fail in Qiskit 2.x. — ⚙️ proven in s2-q013

Traps:

  • output="matplotlib" and output="figure" both raise VisualizationError listing the four real names, from the method and circuit_drawer alike. — ⚙️ proven in s2-q015
  • The standalone drawer is circuit_drawer(qc, output="text") from qiskit.visualization; qiskit.tools no longer exists, and the kwarg is output=, never format=. — ⚙️ proven in s2-q014
  • reverse_bits=True is rendering-only: highest-index qubit on the top wire, with no change to the circuit, the gate order, or the endianness of the results. — ⚙️ proven in s2-q012
  • initial_state=True (default False) draws the |0⟩ labels; the plural initial_states= is a TypeError, and style={"initial_state": True} is silently ignored by the text renderer. — ⚙️ proven in s2-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_histogramplot_distribution
plotsraw countsa normalized quasi-probability distribution
y-axis labelCountQuasi-probability
heights add up tothe shot count1.0
where normalization comes from—the counts themselves

Display options: legend (a LIST of strings, one per execution), sort ("asc" or "desc"), number_to_keep, color, bar_labels and figsize.

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.

FunctionTakesColours
plot_gate_map(backend)a BackendV2nothing; plot_directed=True adds arrows, not error data
plot_error_map(backend)a BackendV2every qubit and every link, from calibration data
plot_circuit_layout(isa, backend)a transpiled circuit plus its backenda 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 for DEVICE questions — which qubits exist, how they connect, how good they are, where the transpiler put your circuit — never measurement outcomes.

Sources: visualization · visualize-results

Must know:

  • The SamplerV2 BitArray is not a counts mapping and has no bare .counts() method — convert with result[0].data.meas.get_counts(). — ⚙️ proven in s2-q022
  • number_to_keep=2 on four outcomes draws three bars — the two largest plus rest, whose height is the SUM of the folded counts (20 + 4 → 24), never their average. — ⚙️ proven in s2-q021
  • Overlaying runs: legend must be a list matching the list of counts dicts — a bare string legend raises, and labels= does not exist. — ⚙️ proven in s2-q023
  • plot_circuit_layout reads circuit.layout, carried only by the circuit transpile RETURNS (its input is never mutated): plotting the original raises QiskitError: 'Circuit has no layout. Perhaps it has not been transpiled.' at every optimization level. — ⚙️ proven in s2-q036
  • Statevector.sample_counts(shots) returns a qiskit.result.Counts mapping summing to shots with only nonzero-amplitude outcomes, so it feeds plot_histogram with no backend or primitive involved; sample_memory(shots) is the per-shot list and sv.seed(...) makes the draw reproducible. — ⚙️ proven in s2-q039

Traps:

  • Flipping qubits 0 and 2 of a 4-qubit register puts the single histogram bar at '0101', not '1010' — qubit 0 is the rightmost character. — ⚙️ proven in s2-q019
  • Neither plotter has a shots= parameter: plot_distribution(counts, shots=1024) raises TypeError, and the V1-era plot_histogram(counts, shots=1024) is gone. — ⚙️ proven in s2-q020
  • With no options, plot_histogram sorts bars in ascending lexicographic bitstring order — not insertion order, not bar height. — ⚙️ proven in s2-q025
  • plot_gate_map given a counts mapping, a CouplingMap or a Target raises AttributeError; plot_histogram(backend) raises too. — ⚙️ proven in s2-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).

PlotDrawsAnswers
plot_bloch_multivector(state)one sphere per qubit, from that qubit's reduced statewhere each qubit points
plot_state_qsphere(state)one node per nonzero amplitude, sized and colouredwhich 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 magnitudethe same matrix, at a glance
plot_state_paulivec(state)the expansion coefficients over Pauli stringsthe 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.

ArrowStateHow you land there
+Z (north pole)the zero statethe starting point
−Z (south pole)the one state—
+Xthe plus stateh alone
−Xthe minus state, the −1 eigenstate of X—
+Ythe 'r' state, a +i relative phaseh then s, a 90° rotation about Z
−Ythe 'l' state, a −i relative phase—

Anywhere on the equator means ⟨Z⟩ = 0. It shows only single-qubit expectation values, so 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_multivector packs one sphere PER QUBIT (3 qubits → 3 spheres, idle ones included) into a single returned Figure. — ⚙️ proven in s2-q026
  • For a Bell state both reduced Bloch vectors are exactly (0, 0, 0) with purity 0.5 — arrows at the centre are 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 in s2-q031
  • plot_bloch_multivector draws REDUCED states, so partial entanglement SHORTENS arrows: after ry(2π/3, 0); cx(0, 1); h(1) qubit 0 points along −z and qubit 1 along −x, both at length 0.5. Full length means a pure single-qubit state. — ⚙️ proven in s2-q047
  • plot_state_paulivec draws a bar only for Pauli strings with a NON-zero expectation value, labelled little-endian: x(1); h(0); s(0) gives exactly II, IY, ZI, ZY at +1, +1, −1, −1, and the qubit-swapped preparation gives YI, IZ, YZ instead. — ⚙️ proven in s1-q067

Traps:

  • Passing a quantum state to plot_bloch_vector does not produce per-qubit spheres — it wants an explicit [x, y, z]. — ⚙️ proven in s2-q034
  • sv.draw("qsphere") works; sv.qsphere(), sv.plot(...) and importing plot_qsphere fail, and any other token raises ValueError listing the valid ones. — ⚙️ proven in s2-q029
  • rz(π/2) on |0⟩ changes only a global phase, so the arrow stays pinned at the north pole, while h and h; s both land on the equator. — ⚙️ proven in s2-q035
Exam checklist
  • Name the four draw outputs 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 SamplerV2 result with result[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.
  • 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).