aperta.visualization

Plotting helpers for the patterns that recur across aperta notebooks.

Two patterns dominate accessibility-notebook visualisations:

  1. Cell choropleth — colour each cell by a per-cell value (typically an accessibility metric or some derived per-cell quantity). plot_cell_values handles the single-panel case; plot_cell_values_comparison handles side-by-side multi-panel with a shared colour scale (before/after, walk vs car, etc.).

  2. Tiered destination viz — for one origin cell, draw the origin, its cell-tier dests, its zone-tier dests, and the underlying network nodes. plot_tiered_destinations packages this.

These helpers exist to keep notebook cells focused on the substantive computation rather than matplotlib boilerplate. They’re not meant to cover every plotting need — drop down to matplotlib directly for one-off custom visuals. Future work can extend this module with helpers for path-feature maps, density choropleths, route-line overlays, and so on.

aperta.visualization.plot_cell_values(cells, values, *, ax=None, title=None, cmap='viridis', vmin=None, vmax=None, missing_color='lightgrey', overlays=None, boundary=None, legend=True, treat_neg_inf_as_missing=True)[source]

Colour each cell by a per-cell value (single-panel choropleth).

Parameters:
  • cells (GeoDataFrame) – cell-indexed GeoDataFrame (index = cell_id; geometry column present).

  • values (Series | dict | str) – per-cell values, one of: pd.Series keyed by cell_id, a dict keyed by cell_id, or the name of a column already on cells. Cells absent from a Series / dict are drawn as missing (missing_color).

  • ax (Axes | None) – existing axes; if None, a new figure + axes is created.

  • title (str | None) – optional axes title.

  • cmap (str) – standard matplotlib choropleth args. vmin / vmax None → auto-scaled from the data.

  • vmin (float | None) – standard matplotlib choropleth args. vmin / vmax None → auto-scaled from the data.

  • vmax (float | None) – standard matplotlib choropleth args. vmin / vmax None → auto-scaled from the data.

  • missing_color (str) – fill colour for cells with NaN value.

  • overlays (list[tuple[GeoDataFrame, dict]] | None) – list of (GeoDataFrame, kwargs) tuples to overlay on top of the choropleth in order (e.g. supermarkets, routes, network).

  • boundary (GeoDataFrame | None) – optional area-of-interest polygon to outline on top (drawn after overlays).

  • legend (bool) – show the colour-scale legend.

  • treat_neg_inf_as_missing (bool) – replace -inf with NaN before plotting. Useful for logsum outputs where unreachable cells produce -inf (drawn as missing rather than as a colour-bar extreme).

Returns:

The Axes object the plot was drawn on.

Return type:

Axes

aperta.visualization.plot_cell_values_comparison(cells, values_by_label, *, suptitle=None, figsize=None, cmap='viridis', missing_color='lightgrey', overlays=None, boundary=None, shared_scale=True, treat_neg_inf_as_missing=True, legend=True)[source]

Side-by-side cell choropleths with a shared colour scale.

Parameters:
  • cells (GeoDataFrame) – cell-indexed GeoDataFrame.

  • values_by_label (dict[str, Series | dict | str]) – ordered dict {panel_title -> per-cell values}. One panel per entry. Values may be pd.Series / dict / column-name (same as plot_cell_values).

  • suptitle (str | None) – optional figure-level super-title.

  • figsize (tuple[float, float] | None) – figure size; defaults to (7 × n_panels, 7).

  • cmap (str) – see plot_cell_values.

  • missing_color (str) – see plot_cell_values.

  • overlays (list[tuple[GeoDataFrame, dict]] | None) – see plot_cell_values.

  • boundary (GeoDataFrame | None) – see plot_cell_values.

  • legend (bool) – see plot_cell_values.

  • treat_neg_inf_as_missing (bool) – see plot_cell_values.

  • shared_scale (bool) – if True, all panels share vmin / vmax derived from the global min/max across all value series. If False, each panel auto-scales independently.

Returns:

The Figure object. (Each subplot Axes is accessible via fig.axes.)

Return type:

Figure

aperta.visualization.plot_tiered_destinations(cells, zones, pairs, origin_cell_id, *, cell_node_column='node_id', zone_node_column='node_id', graph=None, boundary=None, ax=None, title=None, legend=True)[source]

Visualise the tiered OD structure from one origin cell.

Draws, in z-order back-to-front:
  • All cells in pale grey (background).

  • All zone boundaries (faint outlines).

  • Far-tier destination zones (zones_to_zones) for the origin’s zone (pale blue fill).

  • Middle-tier destination zones (cells_to_zones) for the origin cell (mid blue-green fill — distinct from far-tier so the two layers read separately when they overlap).

  • Cell-tier destination cells (cells_to_cells) for the origin (gold fill).

  • The origin cell itself (red).

  • (If graph given) Network nodes as markers: origin (red star), cell-tier dest nodes (small orange dots), middle-tier dest zone nodes (medium teal squares), far-tier dest zone nodes (larger blue squares).

Currently supports TieredODNodePairs only (the node-keyed pairs returned by od_pairs.get_pairs). For geo-keyed pairs, lookup happens via cell_id / zone_id directly — straightforward to add when needed.

Parameters:
  • cells (GeoDataFrame) – cell-indexed GeoDataFrame. Must have cell_node_column and a ‘zone_id’ column.

  • zones (GeoDataFrame) – zone-indexed GeoDataFrame. Must have zone_node_column.

  • pairs (TieredODPairs) – TieredODNodePairs (node-keyed). cells_to_cells and cells_to_zones keys are cell-tier network nodes; zones_to_zones keys are zone-tier network nodes.

  • origin_cell_id – index value of the cell to highlight as the origin (looked up in cells).

  • cell_node_column (str) – column on cells carrying the cell-tier network node ID. Default ‘node_id’.

  • zone_node_column (str) – column on zones carrying the zone-tier network node ID. Default ‘node_id’.

  • graph – optional networkx graph (or any object with a .nodes mapping providing ‘x’ / ‘y’ attributes per node). Enables the node-marker overlay; omit to draw cells/zones only.

  • boundary (GeoDataFrame | None) – optional AOI boundary to outline on top.

  • ax (Axes | None) – existing axes; if None, a new figure + axes is created.

  • title (str | None) – axes title.

  • legend (bool) – show the marker legend (only meaningful when graph is given).

Returns:

The Axes object the plot was drawn on.

Return type:

Axes

aperta.visualization.add_styled_colorbar(ax, *, cmap, vmin, vmax, label, size='3%', pad=0.1, extend='max')[source]

Append a height-matched colour bar to the right of ax.

Wraps the mpl_toolkits.axes_grid1.make_axes_locatable + ScalarMappable pattern that recurs in every map cell. Factored out so notebook cells don’t repeat the four-line ritual.

Parameters:
  • ax – target axes; colour bar appends to its right via make_axes_locatable.

  • cmap – matplotlib colormap (Colormap or name).

  • vmin (float) – data range the colour bar covers.

  • vmax (float) – data range the colour bar covers.

  • label (str) – colour bar label.

  • size (str) – width of colour bar relative to ax (matplotlib syntax, default ‘3%’).

  • pad (float) – padding between ax and the colour bar in inches.

  • extend (str) – arrow indicator for out-of-range values (‘neither’, ‘min’, ‘max’, ‘both’).

Returns:

The newly-created colour-bar axes object.

aperta.visualization.plot_edge_values(graph, values, *, ax=None, cmap='viridis', vmin=None, vmax=None, edge_widths=1.0, sort_key=None, default_value=0.0)[source]

Plot per-edge values on a network using a LineCollection.

The LineCollection approach (over per-edge ax.plot) is ~10× faster on large graphs and lets the caller control draw order by sorting edges before adding them to the collection. sort_key= is the z-order knob: for a “high-tier roads on top” effect on an OSM-derived graph, sort ascending by OSM_HIGHWAY_RANKS and the motorways land last (= drawn on top of) the residential mesh.

Uses d[‘geometry’] from each edge if present (always true post- network_processing.consolidate_intersections); falls back to a straight line between endpoint node positions otherwise.

Parameters:
  • graph (MultiDiGraph) – a networkx graph with x/y on every node and optionally geometry (LineString) on each edge.

  • values (dict | Series) – per-edge value mapping (u, v, k) -> float, either a dict or a pd.Series with a MultiIndex of edge keys. Missing keys get default_value.

  • ax – matplotlib axes; new figure created if None.

  • cmap – matplotlib colormap (Colormap or name).

  • vmin (float | None) – colour-scale range. None auto-derives from data.

  • vmax (float | None) – colour-scale range. None auto-derives from data.

  • edge_widths (dict[tuple, float] | float) – per-edge line width — scalar applies uniformly, dict maps (u, v, k) -> width. Defaults to 1.0.

  • sort_key (Callable[[tuple, dict], Any] | None) – optional (edge_key, edge_data) -> sortable callable that controls draw order (ascending → drawn last on top). None preserves graph iteration order.

  • default_value (float) – fallback for edges missing from values.

Returns:

The matplotlib Axes. Caller is responsible for the colour bar (use add_styled_colorbar), title, axes limits, aspect, etc.