Skip to content

carto_flow.flow_cartogram.visualization

Visualization utilities for cartogram results.

Plotting and animation utilities for morphing results and algorithm analysis.

Functions:

Examples:

>>> from carto_flow.flow_cartogram import morph_gdf, MorphOptions
>>> from carto_flow.flow_cartogram.visualization import plot_comparison, plot_convergence
>>> cartogram = morph_gdf(gdf, "population", options=MorphOptions.preset_fast())
>>> plot_comparison(gdf, cartogram)
>>> plot_convergence(cartogram.snapshots)

Classes:

  • DensityPlotOptions

    Options for density field rendering in static plots and animations.

  • VelocityPlotOptions

    Options for velocity field rendering in static plots and animations.

DensityPlotOptions dataclass

DensityPlotOptions(
    normalize: str | None = None,
    cmap: str | None = None,
    alpha: float = 1.0,
    clip_percentile: float | None = None,
    max_scale: float | None = None,
    vmin: float | None = None,
    vmax: float | None = None,
    colorbar_kwargs: dict = dict(),
    imshow_kwargs: dict = dict(),
)

Options for density field rendering in static plots and animations.

Passing the same DensityPlotOptions instance to both plot_density_field and animate_fields guarantees identical rendering.

Parameters:

  • normalize (str, default: None ) –

    Density normalization: None (absolute values), "difference" (rho - target), or "ratio" (rho / target, log scale).

  • cmap (str, default: None ) –

    Colormap name. Defaults based on normalize.

  • alpha (float, default: 1.0 ) –

    Transparency of the density heatmap.

  • clip_percentile (float, default: None ) –

    Clip color range to exclude outliers (difference mode only). Value in [0, 100] specifies percentile from each end.

  • max_scale (float, default: None ) –

    Fixed maximum for symmetric color scale. For difference mode sets range to [-max_scale, max_scale]; for ratio mode sets [1/max_scale, max_scale].

  • vmin (float, default: None ) –

    Override color-scale minimum.

  • vmax (float, default: None ) –

    Override color-scale maximum.

  • colorbar_kwargs (dict, default: dict() ) –

    Extra keyword arguments forwarded to fig.colorbar().

  • imshow_kwargs (dict, default: dict() ) –

    Extra keyword arguments forwarded to ax.imshow().

VelocityPlotOptions dataclass

VelocityPlotOptions(
    skip: int = 4,
    velocity_scale: float | None = None,
    ref_magnitude: float | None = None,
    color: str = "white",
    alpha: float = 0.8,
    color_by: str | None = None,
    cmap: str | None = None,
    colorbar: bool = True,
    alpha_by_magnitude: bool = False,
    alpha_range: tuple = (0.2, 1.0),
    colorbar_kwargs: dict = dict(),
    quiver_kwargs: dict = dict(),
)

Options for velocity field rendering in static plots and animations.

Passing the same VelocityPlotOptions instance to both plot_velocity_field and animate_fields guarantees identical rendering.

Parameters:

  • skip (int, default: 4 ) –

    Plot every nth velocity arrow to reduce clutter.

  • velocity_scale (float, default: None ) –

    Arrow length as a fraction of grid cell size at the reference magnitude. If None, matplotlib auto-scales.

  • ref_magnitude (float, default: None ) –

    Reference velocity magnitude for arrow scaling. Defaults to the maximum magnitude in the field. Pass the same value to multiple calls for consistent scaling.

  • color (str, default: "white" ) –

    Base arrow color when color_by is None.

  • alpha (float, default: 0.8 ) –

    Base arrow transparency.

  • color_by (str, default: None ) –

    Color arrows by "magnitude" or "direction". None for solid color.

  • cmap (str, default: None ) –

    Colormap when color_by is set.

  • colorbar (bool, default: True ) –

    Whether to show a colorbar when color_by is set.

  • alpha_by_magnitude (bool, default: False ) –

    Vary arrow transparency with velocity magnitude.

  • alpha_range (tuple[float, float], default: (0.2, 1.0) ) –

    Min/max alpha when alpha_by_magnitude is True.

  • colorbar_kwargs (dict, default: dict() ) –

    Extra keyword arguments forwarded to fig.colorbar().

  • quiver_kwargs (dict, default: dict() ) –

    Extra keyword arguments forwarded to ax.quiver().

plot_cartogram

plot_cartogram(
    cartogram: Cartogram,
    ax: Optional[Axes] = None,
    column: str | None = None,
    iteration: int | None = None,
    cmap: str = "RdYlGn_r",
    legend: bool = True,
    **kwargs: Any,
) -> CartogramPlotResult

Plot morphed geometries from a Cartogram.

Parameters:

  • cartogram (Cartogram) –

    Cartogram containing morphed geometries to plot.

  • ax (Axes, default: None ) –

    Axes to plot on. If None, creates new figure.

  • column (str, default: None ) –

    Column to use for coloring geometries. Special values: - '_morph_error_pct': Percentage errors (default if available) - '_morph_density': Density values - Any column from source GeoDataFrame If None, uses '_morph_error_pct' if available, otherwise no coloring.

  • iteration (int, default: None ) –

    Which iteration snapshot to plot (default: latest).

  • cmap (str, default: 'RdYlGn_r' ) –

    Matplotlib colormap name.

  • legend (bool, default: True ) –

    Show colorbar legend when plotting by column.

  • **kwargs (Any, default: {} ) –

    Additional arguments passed to GeoDataFrame.plot()

Returns:

  • CartogramPlotResult

    Result with the axes and named artist references.

Examples:

>>> from carto_flow import morph_gdf
>>> from carto_flow.flow_cartogram.visualization import plot_cartogram
>>> cartogram = morph_gdf(gdf, 'population')
>>> plot_cartogram(cartogram)
>>> plot_cartogram(cartogram, column='population', cmap='Blues')

plot_comparison

plot_comparison(
    left: Any,
    right: Cartogram,
    column: str | None = None,
    iteration: int | None = None,
    left_iteration: int | None = None,
    figsize: tuple[float, float] = (14, 6),
    **kwargs: Any,
) -> CartogramComparisonResult

Side-by-side comparison of two geometries.

Supports comparing: - A GeoDataFrame (original) with a Cartogram (result) - Two Cartogram objects (e.g., different parameters or iterations)

Parameters:

  • left (GeoDataFrame or Cartogram) –

    Left panel: original GeoDataFrame or a Cartogram to compare.

  • right (Cartogram) –

    Right panel: Cartogram containing transformed geometries.

  • column (str, default: None ) –

    Column to use for coloring geometries.

  • iteration (int, default: None ) –

    Which iteration snapshot to plot for right (default: latest).

  • left_iteration (int, default: None ) –

    Which iteration snapshot to plot for left when it's a Cartogram (default: latest). Ignored if left is a GeoDataFrame.

  • figsize (tuple, default: (14, 6) ) –

    Figure size (width, height).

  • **kwargs (Any, default: {} ) –

    Additional arguments passed to GeoDataFrame.plot()

Returns:

  • CartogramComparisonResult

    Result with the figure, both axes, and named artist references.

Examples:

>>> from carto_flow import morph_gdf
>>> from carto_flow.flow_cartogram.visualization import plot_comparison
>>> cartogram = morph_gdf(gdf, 'population')
>>> # Compare original GeoDataFrame with cartogram result
>>> plot_comparison(gdf, cartogram)
>>> plot_comparison(gdf, cartogram, column='population')
>>> # Compare two cartograms (e.g., different parameters)
>>> cartogram_fast = morph_gdf(gdf, 'population', options=MorphOptions.preset_fast())
>>> cartogram_quality = morph_gdf(gdf, 'population', options=MorphOptions.preset_quality())
>>> plot_comparison(cartogram_fast, cartogram_quality)

plot_convergence

plot_convergence(
    cartogram: Cartogram,
    ax: Optional[Axes] = None,
    show_both: bool = True,
    use_pct: bool = True,
    show_tolerance: bool = True,
    show_recompute: bool = False,
    **kwargs: Any,
) -> ConvergencePlotResult

Plot convergence metrics (mean/max error) over iterations.

Parameters:

  • cartogram (Cartogram) –

    Cartogram result object. Uses convergence history if available (all iterations), otherwise falls back to snapshots (sparse).

  • ax (Axes, default: None ) –

    Axes to plot on. If None, creates new figure.

  • show_both (bool, default: True ) –

    If True, shows both mean and max error on separate y-axes. If False, only shows mean error.

  • use_pct (bool, default: True ) –

    If True, shows percentage errors (more interpretable). If False, shows log2 errors (raw algorithm metric).

  • show_tolerance (bool, default: True ) –

    If True, shows horizontal lines indicating error tolerances from the MorphOptions used for computation.

  • show_recompute (bool, default: False ) –

    If True, shows vertical lines indicating iterations where density fields were recomputed.

  • **kwargs (Any, default: {} ) –

    Additional arguments passed to plt.plot()

Returns:

  • ConvergencePlotResult

    Result with the axes and named artist references.

Examples:

>>> from carto_flow import morph_gdf
>>> from carto_flow.flow_cartogram.visualization import plot_convergence
>>> cartogram = morph_gdf(gdf, 'population')
>>> plot_convergence(cartogram)
>>> plot_convergence(cartogram, show_recompute=True)

plot_density_field

plot_density_field(
    cartogram: Cartogram,
    *,
    iteration: int | None = None,
    ax: Optional[Axes] = None,
    bounds: Any | None = None,
    density: Optional[DensityPlotOptions] = None,
) -> DensityFieldResult

Visualize density field as a heatmap.

Parameters:

  • cartogram (Cartogram) –

    Cartogram containing internals with density field data. Requires morphing with save_internals=True in MorphOptions.

  • iteration (int, default: None ) –

    Which iteration snapshot to visualize (default: latest).

  • ax (Axes, default: None ) –

    Axes to plot on. If None, creates new figure.

  • bounds (str, float, or tuple, default: None ) –

    Clip view to specified bounds (removes grid margin): - None: Show full grid extent (default) - "data": Clip to original data bounds (no margin) - float: Data bounds + margin as fraction (e.g., 0.1 = 10% margin) - tuple: (xmin, ymin, xmax, ymax) custom bounds

  • density (DensityPlotOptions, default: None ) –

    Rendering options for the density field. Key fields:

    • normalize: None (absolute), "difference", or "ratio".
    • clip_percentile: Clip outliers for difference mode.
    • max_scale: Fixed symmetric color scale maximum.
    • cmap: Override colormap.
    • vmin/vmax: Override color-scale limits.
    • colorbar_kwargs: Passed to plt.colorbar().
    • imshow_kwargs: Passed to ax.imshow().

Returns:

  • DensityFieldResult

    Result with the axes and named artist references.

Examples:

>>> from carto_flow import morph_gdf, MorphOptions
>>> from carto_flow.flow_cartogram.visualization import plot_density_field, DensityPlotOptions
>>> cartogram = morph_gdf(gdf, 'pop', options=MorphOptions(save_internals=True))
>>> plot_density_field(cartogram)
>>> # Clip to original data bounds (no margin)
>>> plot_density_field(cartogram, bounds="data")
>>> # Show density difference from equilibrium (centered at 0)
>>> plot_density_field(cartogram, density=DensityPlotOptions(normalize="difference"))
>>> # Clip outliers to [2nd, 98th] percentiles for difference mode
>>> plot_density_field(cartogram, density=DensityPlotOptions(normalize="difference", clip_percentile=2))
>>> # Show density ratio to equilibrium (centered at 1)
>>> plot_density_field(cartogram, density=DensityPlotOptions(normalize="ratio"))
>>> # Compare first and last iterations with consistent color scale
>>> fig, (ax1, ax2) = plt.subplots(1, 2)
>>> opts = DensityPlotOptions(normalize="ratio", max_scale=4)
>>> plot_density_field(cartogram, iteration=0, ax=ax1, density=opts)
>>> plot_density_field(cartogram, ax=ax2, density=opts)

plot_velocity_field

plot_velocity_field(
    cartogram: Cartogram,
    *,
    iteration: int | None = None,
    ax: Optional[Axes] = None,
    bounds: Any | None = None,
    velocity: Optional[VelocityPlotOptions] = None,
) -> VelocityFieldResult

Visualize velocity field as a quiver plot.

Parameters:

  • cartogram (Cartogram) –

    Cartogram containing internals with velocity field data. Requires morphing with save_internals=True in MorphOptions.

  • iteration (int, default: None ) –

    Which iteration snapshot to visualize (default: latest).

  • ax (Axes, default: None ) –

    Axes to plot on. If None, creates new figure.

  • bounds (str, float, or tuple, default: None ) –

    Clip view to specified bounds (removes grid margin): - None: Show full grid extent (default) - "data": Clip to original data bounds (no margin) - float: Data bounds + margin as fraction (e.g., 0.1 = 10% margin) - tuple: (xmin, ymin, xmax, ymax) custom bounds

  • velocity (VelocityPlotOptions, default: None ) –

    Rendering options for the velocity field. Key fields:

    • skip: Plot every nth arrow (default 4).
    • velocity_scale: Arrow length as fraction of grid cell spacing.
    • ref_magnitude: Reference magnitude for consistent scaling.
    • color / alpha: Base arrow color and transparency.
    • color_by: None, "magnitude", or "direction".
    • cmap: Colormap when color_by is set.
    • colorbar: Whether to show a colorbar (default True).
    • alpha_by_magnitude: Vary alpha with velocity magnitude.
    • alpha_range: Min/max alpha for magnitude-based transparency.
    • colorbar_kwargs: Passed to plt.colorbar().
    • quiver_kwargs: Passed to ax.quiver().

Returns:

  • VelocityFieldResult

    Result with the axes and named artist references.

Examples:

>>> from carto_flow import morph_gdf, MorphOptions
>>> from carto_flow.flow_cartogram.visualization import plot_velocity_field, VelocityPlotOptions
>>> cartogram = morph_gdf(gdf, 'pop', options=MorphOptions(save_internals=True))
>>> plot_velocity_field(cartogram)
>>> # Color by magnitude
>>> plot_velocity_field(cartogram, velocity=VelocityPlotOptions(color_by="magnitude", cmap="plasma"))
>>> # Color by direction (uses cyclic colormap by default)
>>> plot_velocity_field(cartogram, velocity=VelocityPlotOptions(color_by="direction"))
>>> # Transparency by magnitude (fade out weak velocities)
>>> plot_velocity_field(cartogram, velocity=VelocityPlotOptions(alpha_by_magnitude=True))
>>> # Compare two velocity fields with consistent arrow scaling
>>> fig, (ax1, ax2) = plt.subplots(1, 2)
>>> opts = VelocityPlotOptions(velocity_scale=1.0, ref_magnitude=0.5)
>>> plot_velocity_field(cartogram, iteration=0, ax=ax1, velocity=opts)
>>> plot_velocity_field(cartogram, ax=ax2, velocity=opts)

plot_workflow_convergence

plot_workflow_convergence(
    workflow: CartogramWorkflow,
    ax: Optional[Axes] = None,
    use_pct: bool = True,
    show_tolerance: bool = True,
    show_run_boundaries: bool = True,
    metric: str = "both",
    color_by_run: bool = True,
    cmap: str = "tab10",
    figsize: tuple[float, float] = (12, 6),
    **kwargs: Any,
) -> WorkflowConvergencePlotResult

Plot convergence history across all cartograms in a workflow.

Shows the sequential convergence of multiple morphing runs on a single plot, with cumulative iterations on the x-axis and run boundaries indicated. Useful for visualizing multi-resolution or iterative refinement workflows.

Parameters:

  • workflow (CartogramWorkflow) –

    Workflow containing multiple cartogram results.

  • ax (Axes, default: None ) –

    Axes to plot on. If None, creates new figure.

  • use_pct (bool, default: True ) –

    Show percentage errors (True) or log2 errors (False).

  • show_tolerance (bool, default: True ) –

    Show horizontal tolerance lines from MorphOptions.

  • show_run_boundaries (bool, default: True ) –

    Show vertical dashed lines at run boundaries.

  • metric (str, default: "both" ) –

    Which error metric to show: "mean", "max", or "both". When "both", uses dual y-axes (max on left, mean on right).

  • color_by_run (bool, default: True ) –

    Use different colors for each run. If False, uses single color.

  • cmap (str, default: "tab10" ) –

    Colormap for distinguishing runs when color_by_run=True.

  • figsize (tuple, default: (12, 6) ) –

    Figure size (width, height) if creating new figure.

  • **kwargs (Any, default: {} ) –

    Additional arguments passed to plt.plot().

Returns:

  • WorkflowConvergencePlotResult

    Result with the axes and named artist references.

Examples:

>>> workflow = CartogramWorkflow(gdf, 'population')
>>> workflow.morph_multiresolution(levels=3)
>>> plot_workflow_convergence(workflow)
>>> # Show only mean error with custom colors
>>> plot_workflow_convergence(workflow, metric="mean", cmap="Set2")
>>> # Show log2 errors instead of percentage
>>> plot_workflow_convergence(workflow, use_pct=False)