Seats-votes plots in LaTeX

TikzSeatsVotesPlot follows the same election vocabulary as the Matplotlib builder: add target-party vote counts plus totals, or provide district shares alone. The resulting uniform-swing step curve, observed marker, and benchmark lines render as native TikZ. Use this builder when the final figure should inherit a LaTeX document’s fonts and scaling.

import numpy as np

from gerrytools.latex import TikzSeatsVotesPlot

democratic_votes = np.array([42_000, 48_000, 53_000, 57_000, 62_000, 68_000])
total_votes = np.array([100_000, 99_000, 101_000, 98_000, 102_000, 100_000])

plot = TikzSeatsVotesPlot()
plot.add_election(
    democratic_votes,
    total_votes,
    linecolor="denim",
    markercolor="alizarin",
    marker_label="Observed result",
)
plot.add_proportionality_line()
plot.add_efficiency_gap_line()
print(plot)
\documentclass[border=2pt]{standalone}
\usepackage{latexcolors, tikz}
\begin{document}
\begin{tikzpicture}
\begin{scope}[xscale=10.0, yscale=10.0]
\clip [draw] (0.0000, 0.0000) rectangle (1.0000, 1.0000);

{\color[HTML]{D3D3D3}\fill [fill opacity=1.0000] (0.4900, 0.0000) rectangle (0.5100, 1.0000);}
{\color[HTML]{D3D3D3}\fill [fill opacity=1.0000] (0.0000, 0.4900) rectangle (1.0000, 0.5100);}

{\color{gray}\draw [line width=1.00pt, dashed] (0.0000, 0.0000) -- (1.0000, 1.0000);}
{\color{gray}\draw [line width=1.00pt, solid] (0.2500, 0.0000) -- (0.7500, 1.0000);}

{\color{denim}\draw [line width=1.50pt] (0.0000, 0.0000) -- (0.0000, 0.0000) -- (0.3700, 0.0000) -- (0.3700, 0.1667) -- (0.4422, 0.1667) -- (0.4422, 0.3333) -- (0.4684, 0.3333) -- (0.4684, 0.5000) -- (0.5252, 0.5000) -- (0.5252, 0.6667) -- (0.5652, 0.6667) -- (0.5652, 0.8333) -- (0.6300, 0.8333) -- (0.6300, 1.0000) -- (1.0000, 1.0000);}

{\color{alizarin}\node [circle, inner sep=0pt, minimum size=8.00pt, fill, draw] at (0.5500, 0.6667) {};}
\end{scope}
\end{tikzpicture}

\end{document}

TikZ seats-votes plot with benchmark lines

Counts preserve district turnout when the observed statewide vote share is calculated. If only district shares are supplied, the observed share is their unweighted mean. Repeated add_election() calls place several elections on the same axes, as in the Matplotlib builder.

Printing the plot shows the complete standalone source, including its preamble. plot.print() writes the TikZ body alone for pasting into an existing report. preview(), plot.document.save_pdf(), and plot.document.save_png() compile the standalone document through the local LaTeX installation.