carto_flow.flow_cartogram.animation¶
Animation utilities for cartogram results.
Animation functions for visualizing morphing results, including geometry transitions, density field evolution, and velocity field dynamics.
Functions:
-
animate_morph_history–Animate through algorithm snapshots.
-
animate_geometry_keyframes–Animate between arbitrary geometry states.
-
animate_density_field–Animate density field evolution.
-
animate_velocity_field–Animate velocity field evolution.
-
save_animation–Save animations to various formats.
Examples:
>>> from carto_flow import CartogramWorkflow, MorphOptions
>>> from carto_flow.flow_cartogram.animation import animate_morph_history, save_animation
>>>
>>> workflow = CartogramWorkflow(gdf, 'population')
>>> cartogram = workflow.morph(options=MorphOptions(save_history=True))
>>> anim = animate_morph_history(cartogram, duration=5.0, fps=15)
>>> save_animation(anim, "morph.gif", fps=15)
animate_density_field
¶
animate_density_field(
cartogram: Cartogram,
*,
duration: float = 5.0,
fps: int = 15,
interpolation: str = "nearest",
position_mapper: PositionMapper | None = None,
bounds: Any | None = None,
density: Optional[DensityPlotOptions] = None,
show_axes: bool = True,
title: str | bool | None = None,
figsize: tuple[float, float] = (10, 8),
) -> FuncAnimation
Animate density field evolution. Convenience wrapper for animate_fields.
See animate_fields for full documentation.
animate_fields
¶
animate_fields(
cartogram: Cartogram,
*,
duration: float = 5.0,
fps: int = 15,
interpolation: str = "nearest",
position_mapper: PositionMapper | None = None,
bounds: Any | None = None,
show_density: bool = True,
show_velocity: bool = False,
density: Optional[DensityPlotOptions] = None,
velocity: Optional[VelocityPlotOptions] = None,
show_axes: bool = True,
title: str | bool | None = None,
figsize: tuple[float, float] = (10, 8),
) -> FuncAnimation
Animate density and/or velocity fields over iterations.
Parameters:
-
cartogram(Cartogram) –Cartogram result with internals (requires save_internals=True)
-
duration(float, default:5.0) –Animation duration in seconds
-
fps(int, default:15) –Frames per second
-
interpolation(str, default:"nearest") –Interpolation method: "nearest" or "linear"
-
position_mapper(callable, default:None) –Function to control animation timing. Use linear_over() factory.
-
bounds(str, float, or tuple, default:None) –Clip view to specified bounds
-
show_density(bool, default:True) –Whether to show density field heatmap
-
show_velocity(bool, default:False) –Whether to show velocity field arrows
-
density(DensityPlotOptions, default:None) –Rendering options for the density field. Key fields:
normalize: None (absolute),"difference", or"ratio".clip_percentile/max_scale: outlier control for difference mode.cmap/alpha: colormap and transparency.vmin/vmax: override the global color-scale limits.colorbar_kwargs: passed tofig.colorbar().imshow_kwargs: passed toax.imshow().
-
velocity(VelocityPlotOptions, default:None) –Rendering options for the velocity field. Key fields:
skip: plot every nth arrow (default 4).velocity_scale/ref_magnitude: arrow length control.color/alpha: base arrow color and transparency.color_by: None,"magnitude", or"direction".colorbar: whether to show a colorbar (default False in animations).colorbar_kwargs: passed tofig.colorbar().quiver_kwargs: passed toax.quiver().
-
show_axes(bool, default:True) –If False, hides the axes frame, ticks, and labels (
ax.axis("off")). Useful for clean map-style animations. -
title(str, bool, or None, default:None) –Controls the axes title each frame.
None: auto-title ("Density Field (iteration N)").Falseor"": no title.str: format-string expanded each frame. Available keys:{iteration},{field}(e.g. "Density Field"),{t}.
-
figsize(tuple, default:(10, 8)) –Figure size (width, height)
Returns:
-
FuncAnimation–Matplotlib animation object
Examples:
>>> from carto_flow.flow_cartogram.visualization import DensityPlotOptions, VelocityPlotOptions
>>> # Density field only (default)
>>> anim = animate_fields(cartogram, density=DensityPlotOptions(normalize="ratio"))
animate_geometry_keyframes
¶
animate_geometry_keyframes(
keyframes: list[Any],
duration: float = 5.0,
fps: int = 15,
interpolation: str = "linear",
position_mapper: PositionMapper | None = None,
keyframe_times: ndarray | None = None,
hold_frames: int = 0,
column: str | None = None,
color_values: list[ndarray] | None = None,
vmin: float | None = None,
vmax: float | None = None,
cmap: str = "viridis",
colorbar: bool = False,
colorbar_label: str | None = None,
show_axes: bool = True,
colorbar_kwargs: dict | None = None,
title: str | bool | None = None,
precompute: bool = True,
figsize: tuple[float, float] = (10, 8),
**kwargs: Any,
) -> FuncAnimation
Animate between arbitrary geometry states (keyframes).
Parameters:
-
keyframes(list) –List of geometry sources. Each can be: - GeoDataFrame - Cartogram (uses latest snapshot's geometry)
-
duration(float, default:5.0) –Animation duration in seconds
-
fps(int, default:15) –Frames per second
-
interpolation(str, default:"linear") –Interpolation method between keyframes: - "nearest": Jump between keyframes (no interpolation) - "linear": Linearly interpolate geometry vertices between keyframes
-
position_mapper(callable, default:None) –Function to control animation timing. Maps progress [0,1] to position in keyframe space [0, n_keyframes-1]. Use linear_over() factory: - linear_over("index"): Linear time-to-keyframe index (default) - linear_over("time"): Linear time-to-time (requires keyframe_times) - linear_over(custom_values): Linear over any custom array Use weights_to_position_mapper() for weight-based functions.
-
keyframe_times(array - like, default:None) –Time values for each keyframe. Must have same length as keyframes. Enables linear_over("time") position mapper. Values should be monotonically increasing.
-
hold_frames(int, default:0) –Number of frames to hold at each keyframe before transitioning. Note: When using a position_mapper, hold_frames is ignored.
-
column(str, default:None) –Column to use for coloring geometries. Values are read from each keyframe's GeoDataFrame and color limits are computed globally.
-
color_values(list of arrays, default:None) –Per-keyframe color values. Each array has one value per geometry. When provided, takes precedence over column. Color values are interpolated when using linear geometry interpolation.
-
vmin(float, default:None) –Minimum value for color scale. If None, computed from all values.
-
vmax(float, default:None) –Maximum value for color scale. If None, computed from all values.
-
cmap(str, default:"viridis") –Colormap name for coloring geometries.
-
colorbar(bool, default:False) –Whether to show a colorbar.
-
colorbar_label(str, default:None) –Label for the colorbar. Defaults to column name if using column.
-
show_axes(bool, default:True) –If False, hides the axes frame, ticks, and labels (
ax.axis("off")). Useful for clean map-style animations. -
colorbar_kwargs(dict, default:None) –Additional keyword arguments passed to
fig.colorbar(). Example:dict(shrink=0.8, pad=0.02). The"label"key overrides the auto-set label. -
title(str, bool, or None, default:None) –Controls the axes title each frame.
None: auto-title ("Keyframe X/N" or transition label).Falseor"": no title.str: format-string expanded withstr.format_map(ctx)each frame. Available keys:{keyframe}(1-based),{n_keyframes},{t}(inter-keyframe fraction in [0, 1]).
-
precompute(bool, default:True) –If True, all frames are computed before the animation starts. Eliminates per-frame geometry interpolation and GeoDataFrame copying, giving a significant speedup especially for
interpolation="linear". Set to False to reduce peak memory usage for very long animations. -
figsize(tuple, default:(10, 8)) –Figure size (width, height)
-
**kwargs(Any, default:{}) –Additional arguments passed to GeoDataFrame.plot()
Returns:
-
FuncAnimation–Matplotlib animation object
Notes
Available variables for position_mapper: - "index": Keyframe indices [0, 1, 2, ...] - "time": Keyframe times (if keyframe_times is provided)
Color limits are computed globally across all keyframes to ensure consistent coloring throughout the animation.
Examples:
>>> # Animate with smooth interpolation (default: linear over index)
>>> anim = animate_geometry_keyframes(
... keyframes=[gdf, result1, result2],
... duration=6.0,
... interpolation="linear",
... )
>>> save_animation(anim, "keyframes.gif", fps=15)
>>> # Animate with changing colors (e.g., population over years)
>>> anim = animate_geometry_keyframes(
... keyframes=[gdf_2020, gdf_2021, gdf_2022],
... color_values=[pop_2020, pop_2021, pop_2022],
... interpolation="linear",
... cmap="plasma",
... colorbar=True,
... colorbar_label="Population"
... )
>>> # Use column from GeoDataFrames with consistent limits
>>> anim = animate_geometry_keyframes(
... keyframes=[gdf1, gdf2, gdf3],
... column="value",
... cmap="RdYlGn",
... )
animate_morph_history
¶
animate_morph_history(
cartogram: Cartogram,
duration: float = 5.0,
fps: int = 15,
interpolation: str = "nearest",
position_mapper: PositionMapper | None = None,
color_by: str | ndarray | list | None = None,
vmin: float | None = None,
vmax: float | None = None,
cmap: str = "viridis",
colorbar: bool = False,
colorbar_label: str | None = None,
show_axes: bool = True,
colorbar_kwargs: dict | None = None,
title: str | bool | None = None,
precompute: bool = True,
figsize: tuple[float, float] = (10, 8),
**kwargs: Any,
) -> FuncAnimation
Animate through algorithm snapshots from a Cartogram's history.
Parameters:
-
cartogram(Cartogram) –Cartogram result with snapshots containing geometry history
-
duration(float, default:5.0) –Animation duration in seconds
-
fps(int, default:15) –Frames per second
-
interpolation(str, default:"nearest") –Interpolation method between snapshots: - "nearest": Show the nearest snapshot (no interpolation) - "linear": Linearly interpolate geometry vertices between snapshots
-
position_mapper(callable, default:None) –Function to control animation timing. Maps progress [0,1] to position in snapshot space [0, n_snapshots-1]. Use linear_over() factory: - linear_over("iteration"): Linear time-to-iteration (default) - linear_over("mean_error"): Linear time-to-mean-error - linear_over("max_error"): Linear time-to-max-error - linear_over(custom_values): Linear over any custom array Use weights_to_position_mapper() for weight-based functions.
-
color_by(str, np.ndarray, or list of np.ndarray, default:None) –What to color geometries by: -
"errors_pct": per-geometry percentage error at each snapshot -"density": per-geometry density (values/area) at each snapshot -"original": values from the column used to build the cartogram (static across snapshots; requirescartogram._value_column) - any other str: column name looked up incartogram._source_gdf(static across snapshots) - np.ndarray: single array broadcast to all snapshots (static) - list of np.ndarray: one array per snapshot -
vmin(float, default:None) –Minimum value for color scale. If None, computed from all values.
-
vmax(float, default:None) –Maximum value for color scale. If None, computed from all values.
-
cmap(str, default:"viridis") –Colormap name for coloring geometries.
-
colorbar(bool, default:False) –Whether to show a colorbar.
-
colorbar_label(str, default:None) –Label for the colorbar. Auto-set from color_by if not provided.
-
show_axes(bool, default:True) –If False, hides the axes frame, ticks, and labels (
ax.axis("off")). Useful for clean map-style animations. -
colorbar_kwargs(dict, default:None) –Additional keyword arguments passed to
fig.colorbar(). Example:dict(shrink=0.8, pad=0.02). The"label"key overrides the auto-set label. -
title(str, bool, or None, default:None) –Controls the axes title each frame. -
None: auto-generated title showing iteration and error (default) -Falseor"": no title - str: format template rendered withstr.format_map()each frame. Available keys:{iteration},{mean_error},{max_error},{mean_error_pct},{max_error_pct},{t}. Unavailable keys (e.g. when no error history was saved) yieldnan. -
precompute(bool, default:True) –If True, all frames are computed before the animation starts. Eliminates per-frame geometry interpolation and GeoDataFrame copying, giving a significant speedup especially for
interpolation="linear". Set to False to reduce peak memory usage for very long animations. -
figsize(tuple, default:(10, 8)) –Figure size (width, height)
-
**kwargs(Any, default:{}) –Additional arguments passed to GeoDataFrame.plot()
Returns:
-
FuncAnimation–Matplotlib animation object
Raises:
-
ValueError–If cartogram.snapshots doesn't contain geometry snapshots
Notes
Available variables for position_mapper (extracted from snapshots): - "iteration": Iteration numbers - "mean_error": Mean log2 errors (if available) - "max_error": Maximum log2 errors (if available) - "index": Snapshot indices [0, 1, 2, ...]
Color limits are computed globally across all snapshots to ensure consistent coloring throughout the animation.
Examples:
>>> workflow = CartogramWorkflow(gdf, 'pop')
>>> cartogram = workflow.morph(options=MorphOptions(save_history=True))
>>> anim = animate_morph_history(cartogram, duration=5.0, fps=15)
>>> save_animation(anim, "morph.gif", fps=15)
>>> # Color by per-geometry error percentage
>>> anim = animate_morph_history(
... cartogram, color_by="errors_pct", cmap="RdYlGn_r", colorbar=True
... )
>>> # Color by per-snapshot density
>>> anim = animate_morph_history(cartogram, color_by="density", cmap="plasma", colorbar=True)
>>> # Color by original data column (static)
>>> anim = animate_morph_history(cartogram, color_by="original", colorbar=True)
>>> anim = animate_morph_history(cartogram, color_by="population", colorbar=True)
animate_velocity_field
¶
animate_velocity_field(
cartogram: Cartogram,
*,
duration: float = 5.0,
fps: int = 15,
interpolation: str = "nearest",
position_mapper: PositionMapper | None = None,
bounds: Any | None = None,
velocity: Optional[VelocityPlotOptions] = None,
show_axes: bool = True,
title: str | bool | None = None,
figsize: tuple[float, float] = (10, 8),
) -> FuncAnimation
Animate velocity field evolution. Convenience wrapper for animate_fields.
See animate_fields for full documentation.
animate_workflow
¶
animate_workflow(
workflow: CartogramWorkflow,
duration: float = 8.0,
fps: int = 15,
interpolation: str = "linear",
hold_at_keyframes: float = 0.5,
color_by: str | ndarray | list | None = "errors_pct",
cmap: str = "RdYlGn_r",
vmin: float | None = None,
vmax: float | None = None,
colorbar: bool = True,
colorbar_label: str | None = None,
show_run_info: bool = True,
show_axes: bool = True,
colorbar_kwargs: dict | None = None,
title: str | bool | None = None,
precompute: bool = True,
figsize: tuple[float, float] = (10, 8),
**kwargs: Any,
) -> FuncAnimation
Animate through all cartograms in a workflow.
Shows smooth transitions from original through all morphing results, with optional hold time at each keyframe (final state of each run).
Parameters:
-
workflow(CartogramWorkflow) –Workflow containing cartogram results.
-
duration(float, default:8.0) –Total animation duration in seconds.
-
fps(int, default:15) –Frames per second.
-
interpolation(str, default:"linear") –Interpolation between keyframes: "nearest" or "linear".
-
hold_at_keyframes(float, default:0.5) –Seconds to pause at each cartogram's final state.
-
color_by(str, array, list, or None, default:"errors_pct") –What to use for coloring geometries. Accepted values:
"errors_pct"(default): per-geometry percentage error from each cartogram'sget_errors().errors_pct."density": per-geometry density from each cartogram'sget_density()."original": static values from the column used to build the cartogram (requires_value_column+_source_gdf; set automatically byCartogramWorkflow).- Any other
str: column looked up in_source_gdffor every cartogram (raisesValueErrorif not found). np.ndarray: single array broadcast to every keyframe.listof arrays: one array per cartogram in the workflow.None: no coloring.
-
cmap(str, default:"RdYlGn_r") –Colormap for coloring geometries.
-
vmin(float, default:None) –Minimum value for color scale. If None, computed from all values.
-
vmax(float, default:None) –Maximum value for color scale. If None, computed from all values.
-
colorbar(bool, default:True) –Whether to show a colorbar.
-
colorbar_label(str, default:None) –Label for the colorbar. Auto-set from
color_byif not provided. -
show_run_info(bool, default:True) –Show "Run X/N" in title during animation.
-
show_axes(bool, default:True) –If False, hides the axes frame, ticks, and labels (
ax.axis("off")). Useful for clean map-style animations. -
colorbar_kwargs(dict, default:None) –Additional keyword arguments passed to
fig.colorbar(). Example:dict(shrink=0.8, pad=0.02). The"label"key overrides the auto-set label. -
title(str, bool, or None, default:None) –Controls the axes title each frame.
None: auto-title (usesshow_run_infologic).Falseor"": no title.str: format-string expanded each frame. Available keys:{run}(0-based keyframe index),{n_runs},{t}(elapsed seconds),{duration}(total seconds),{iteration},{n_iterations},{mean_error},{max_error},{mean_error_pct},{max_error_pct}.
-
precompute(bool, default:True) –If True, all frames are computed before the animation starts. Eliminates per-frame geometry interpolation and GeoDataFrame copying, giving a significant speedup especially for
interpolation="linear". Set to False to reduce peak memory usage for very long animations. -
figsize(tuple, default:(10, 8)) –Figure size (width, height).
-
**kwargs(Any, default:{}) –Additional arguments passed to GeoDataFrame.plot().
Returns:
-
FuncAnimation–Matplotlib animation object.
Examples:
>>> workflow = CartogramWorkflow(gdf, 'population')
>>> workflow.morph_multiresolution(levels=3)
>>> anim = animate_workflow(workflow, duration=10.0)
>>> save_animation(anim, "workflow.gif")
animate_workflow_fields
¶
animate_workflow_fields(
workflow: CartogramWorkflow,
*,
duration: float = 8.0,
fps: int = 15,
interpolation: str = "nearest",
bounds: Any | None = None,
show_density: bool = True,
show_velocity: bool = False,
density: Optional[DensityPlotOptions] = None,
velocity: Optional[VelocityPlotOptions] = None,
show_axes: bool = True,
title: str | bool | None = None,
figsize: tuple[float, float] = (10, 8),
) -> FuncAnimation
Animate density and/or velocity fields across all cartograms in a workflow.
Shows how the fields evolve through multiple morphing runs. Each run displays at its native grid resolution, allowing visualization of multi-resolution workflows where grid detail increases progressively.
Parameters:
-
workflow(CartogramWorkflow) –Workflow containing cartogram results with internals (requires save_internals=True in MorphOptions for each run).
-
duration(float, default:8.0) –Animation duration in seconds.
-
fps(int, default:15) –Frames per second.
-
interpolation(str, default:"nearest") –Interpolation method: "nearest" or "linear".
-
bounds(str, float, or tuple, default:None) –Clip view to specified bounds (same as animate_fields).
-
show_density(bool, default:True) –Whether to show density field heatmap.
-
show_velocity(bool, default:False) –Whether to show velocity field arrows.
-
density(DensityPlotOptions, default:None) –Rendering options for the density field. Defaults to
DensityPlotOptions(normalize="ratio")for workflow animations. See :class:~carto_flow.flow_cartogram.visualization.DensityPlotOptions. -
velocity(VelocityPlotOptions, default:None) –Rendering options for the velocity field. See :class:
~carto_flow.flow_cartogram.visualization.VelocityPlotOptions. -
show_axes(bool, default:True) –If False, hides the axes frame, ticks, and labels (
ax.axis("off")). Useful for clean map-style animations. -
title(str, bool, or None, default:None) –Controls the axes title each frame.
None: auto-title ("Density Field (Run X/N, iter Y)").Falseor"": no title.str: format-string expanded each frame. Available keys:{iteration},{run}(0-based),{n_runs},{field}(e.g. "Density Field"),{t}.
-
figsize(tuple, default:(10, 8)) –Figure size (width, height).
Returns:
-
FuncAnimation–Matplotlib animation object.
Examples:
>>> from carto_flow.flow_cartogram.visualization import DensityPlotOptions, VelocityPlotOptions
>>> workflow = CartogramWorkflow(gdf, 'population')
>>> workflow.morph(options=MorphOptions(save_internals=True))
>>> workflow.morph(options=MorphOptions(save_internals=True))
>>> anim = animate_workflow_fields(workflow, density=DensityPlotOptions(normalize="ratio"))
>>> save_animation(anim, "workflow_fields.gif")
linear_over
¶
Create a position mapper that linearizes animation progress over values.
This factory creates a position mapper where animation progress [0, 1] maps linearly to the specified values. Use this to control which variable determines animation pacing.
Parameters:
-
key_or_values(str or array) –- str: Variable name to extract from the variables dict. Common keys for animate_morph_history: "iteration", "mean_error", "max_error" Common keys for animate_geometry_keyframes: "index", "time"
- array: Values to linearize over directly
-
decreasing(bool, default:None) –Whether values decrease over time (e.g., error values). If None (default), auto-detected: True for keys containing "error", False otherwise.
Returns:
-
PositionMapper–Position mapper function with signature (progress, variables) -> position
Examples:
>>> # Linearize over iteration (default for morph_history)
>>> anim = animate_morph_history(result, position_mapper=linear_over("iteration"))
>>> # Linearize over mean error
>>> anim = animate_morph_history(result, position_mapper=linear_over("mean_error"))
save_animation
¶
save_animation(
anim: FuncAnimation,
path: str | Path,
fps: int = 15,
dpi: int = 100,
**kwargs: Any,
) -> None
Save an animation to file.
Parameters:
-
anim(FuncAnimation) –Animation object to save
-
path(str or Path) –Output path. Format determined by extension: - .gif: Uses pillow writer - .mp4: Uses ffmpeg writer - Directory path: Saves individual PNG frames
-
fps(int, default:15) –Frames per second
-
dpi(int, default:100) –Resolution in dots per inch
-
**kwargs(Any, default:{}) –Additional arguments passed to the writer
Raises:
-
ValueError–If the output format is not supported or required writer is unavailable
weights_to_position_mapper
¶
Convert a weight-based function to a position mapper.
This allows users to define mappers using the simpler weight-based interface (where higher weight = more time at that snapshot) while using the unified position mapper internally.
Parameters:
-
weight_fn(callable) –Function with signature (variables: dict) -> weights array. Higher weights mean more animation time allocated to that item.
Returns:
-
PositionMapper–Position mapper function with signature (progress, variables) -> position
Examples: