carto_flow.flow_cartogram.density¶
Density field computation utilities for cartographic applications.
This module provides functions for computing density fields from geospatial data, which are essential for flow-based cartography algorithms. The main functionality includes rasterizing polygon geometries onto regular grids to create density distributions that drive cartogram deformation processes.
Functions:
-
compute_density_field–Core function for rasterizing polygon data to density grids.
Examples:
>>> from carto_flow.flow_cartogram.density import compute_density_field
>>> from carto_flow.flow_cartogram.grid import Grid
>>> grid = Grid.from_bounds((0, 0, 100, 80), size=100)
>>> density = compute_density_field(gdf, "population", grid)
Classes:
-
DensityBorderExtension–Extend interior density values outward, blending toward the target density.
-
DensityModulator–Abstract base class for density field modulators.
-
DensityPipeline–Sequence of density modulators applied left-to-right.
-
Smooth–Gaussian smoothing of the density field, preserving the global mean.
DensityBorderExtension
¶
DensityBorderExtension(
extension_width: float = 10.0,
transition_width: float = 10.0,
smooth: float | None = None,
)
Bases: DensityModulator
Extend interior density values outward, blending toward the target density.
By default, outside cells are assigned target_density (the
mean equalized density). This can cause a sharp density step at the
outer boundary, which may distort boundary geometries during morphing.
DensityBorderExtension replaces outside-cell densities with a
smooth outward extrapolation of the nearest interior values. Over
extension_width units outside the boundary the interior density is
copied as-is; beyond that it transitions toward target_density over
transition_width units via linear blending.
Parameters:
-
extension_width(float, default:10.0) –Distance in world/data-coordinate units over which interior densities are propagated outward without blending.
-
transition_width(float, default:10.0) –Distance in world/data-coordinate units over which the density blends from the extrapolated interior value to
target_density. Set to 0 for a hard cutoff atextension_width. -
smooth(float or None, default:None) –Optional Gaussian smoothing sigma in world-coordinate units applied to the final density field to remove small artefacts.
Examples:
>>> DensityBorderExtension(extension_width=5, transition_width=20)
>>> DensityBorderExtension(extension_width=10) + DensitySmooth(sigma=2)
Methods:
-
__call__–Extend density values from the interior outward and blend to target.
__call__
¶
Extend density values from the interior outward and blend to target.
DensityModulator
¶
Abstract base class for density field modulators.
Subclasses implement __call__(density, grid, mask, target_density)
and return a modified density array. Modulators can be chained with
+ into a :class:DensityPipeline that applies them left-to-right::
mod = DensityBorderExtension(extension_width=10) + DensitySmooth(sigma=2)
Methods:
DensityPipeline
¶
Bases: DensityModulator
Sequence of density modulators applied left-to-right.
Constructed automatically when two modulators are combined with +.
Further + calls append to the same pipeline rather than nesting::
pipe = DensityBorderExtension() + DensitySmooth(sigma=2)
Methods:
Smooth
¶
Bases: DensityModulator
Gaussian smoothing of the density field, preserving the global mean.
Convolves the density field with an isotropic Gaussian kernel, then
rescales the result so the spatial mean is unchanged. This softens
sharp density boundaries between geometries without shifting the
overall target density. Exported from the package as DensitySmooth
to avoid name collision with the velocity :class:~anisotropy.Smooth.
Parameters:
-
sigma(float, default:1.0) –Standard deviation of the Gaussian kernel in world/data-coordinate units. Converted to pixels at call time.
Examples:
compute_density_field
¶
compute_density_field(
gdf: Any,
column: str,
grid: Grid,
mean_density: float | None = None,
smooth: float | None = None,
) -> np.ndarray
Rasterize polygon geometries to a density grid.
This function computes a density field by rasterizing polygon geometries onto a regular grid. Each polygon's density contribution is calculated as its attribute value divided by its area.
Parameters:
-
gdf(Any) –GeoDataFrame-like object containing polygon geometries. Must have: - 'geometry' column with polygon geometries - Column specified by 'column' parameter with values to use for densities
-
column(str) –Name of the column in gdf containing the variable of interest (e.g., 'population').
-
grid(Grid) –Grid information object containing X, Y meshgrid arrays and grid properties.
-
mean_density(float, default:None) –Background density value for areas outside polygons. If None, computed as total column sum divided by total geometry area sum.
-
smooth(float, default:None) –Standard deviation for Gaussian smoothing. If provided, applies gaussian_filter with this sigma value and preserves global mean.
Returns:
-
rho(ndarray) –2D density array with same shape as grid.X and grid.Y. Contains density values (attribute per unit area) at each grid cell center.
Notes
The function: - Assigns density = polygon_value / polygon_area to cells inside each polygon - Fills exterior cells with mean_density (computed or provided) - Optionally applies Gaussian smoothing while preserving the global mean
Examples:
>>> import geopandas as gpd
>>> from carto_flow.density import compute_density_field
>>> from carto_flow.grid import Grid
>>>
>>> # Create sample data
>>> gdf = gpd.GeoDataFrame({
... 'geometry': [polygon1, polygon2],
... 'population': [1000, 2000]
... })
>>>
>>> # Set up grid
>>> bounds = (0, 0, 10, 10)
>>> grid = Grid.from_bounds(bounds, size=50)
>>>
>>> # Compute density field
>>> density = compute_density_field(gdf, 'population', grid)
>>> print(f"Density grid shape: {density.shape}")
compute_density_field_from_geometries
¶
compute_density_field_from_geometries(
geometries,
column_values,
grid,
mean_density=None,
smooth=None,
return_geometry_mask=False,
return_outside_mask=False,
)
Compute density field directly from geometries (no dataframe dependency).
Parameters:
-
geometries(list of shapely geometries) –The geometries to compute density for.
-
column_values(array - like) –Values associated with each geometry.
-
grid(Grid) –Grid object with X, Y coordinate arrays.
-
mean_density(float, default:None) –Background density for cells outside geometries.
-
smooth(float, default:None) –Gaussian smoothing sigma applied to the entire density field (both inside and outside). Preserves the global mean.
-
return_geometry_mask(bool, default:False) –If True, return tuple (rho, geometry_mask) where geometry_mask is an integer array indicating which geometry each cell belongs to: - -1: Outside all geometries - k: Inside geometry k (0 <= k < number of geometries)
-
return_outside_mask(bool, default:False) –(Deprecated) If True, return tuple (rho, outside_mask) where outside_mask is a boolean array indicating cells outside all geometries.
Returns:
-
rho(ndarray) –Density field array.
-
geometry_mask(np.ndarray (only if return_geometry_mask=True)) –Integer array where each element indicates which geometry the cell belongs to.
-
outside_mask(np.ndarray (only if return_outside_mask=True)) –Boolean array where True indicates cells outside all geometries.
preview_modulator
¶
preview_modulator(
modulator: DensityModulator,
gdf,
grid_size: int = 64,
column: str | None = None,
values=None,
margin: float = 0.1,
show_geometry: bool = True,
show: str = "output",
ax=None,
cmap: str = "RdBu_r",
show_colorbar: bool = True,
colorbar_kwargs: dict | None = None,
image_kwargs: dict | None = None,
area_scale: float = 1.0,
)
Preview a density modulator applied to a computed density field.
Rasterizes the input density from gdf (or uniform values if column and values are both omitted), applies the modulator, and displays the result as a heatmap.
Parameters:
-
modulator(DensityModulator) –The modulator to preview.
-
gdf(GeoDataFrame) –Geometries used to derive the spatial extent, the geometry mask, and (when column is given) the density values.
-
grid_size(int, default:64) –Number of grid cells along the longer axis.
-
column(str, default:None) –Column in gdf to use as per-geometry values. Takes precedence over values.
-
values(array - like, default:None) –Per-geometry values (same length as gdf). Ignored when column is given. If both are
None, uniform values (all 1.0) are used so the input density equals 1 / geometry_area everywhere. -
margin(float, default:0.1) –Fractional margin added around the bounds before building the grid.
-
show_geometry(bool, default:True) –Draw geometry outlines as a light background layer.
-
show(str, default:'output') –Which field to display. One of:
'output'— post-modulation density field (default).'input'— pre-modulation density field.'ratio'— log₁₀ of the element-wise ratiorho_out / rho_in, displayed with a symmetric linear norm (equal multiplicative changes occupy equal visual space); tick labels show actual ratio values.
-
ax(Axes, default:None) –Axes to draw on. A new figure is created if
None. -
cmap(str or Colormap, default:'RdBu_r') –Colormap used for all
showmodes. A diverging colormap is recommended: for'input'and'output'the centre is anchored at target_density (white = equilibrium, blue = below, red = above); for'ratio'the centre is anchored at 1 (no change). -
show_colorbar(bool, default:True) –When
False, the colorbar is omitted. -
colorbar_kwargs(dict, default:None) –Extra keyword arguments for
plt.colorbar. -
image_kwargs(dict, default:None) –Extra keyword arguments merged into the
ax.imshowcall. -
area_scale(float, default:1.0) –Multiplier applied to areas when computing density, matching
MorphOptions.area_scale. For example,1e-6converts m² grid coordinates to km² density units.
Returns:
-
DensityModulatorPreviewResult–Named container with the produced artists:
ax— the axesimage— the :class:~matplotlib.image.AxesImageheatmapcolorbar— :class:~matplotlib.colorbar.Colorbar, orNonegeometry_collections— list of collections fromgdf.plot()
Examples: