HEALPix connected components#

healpix-analyse provides connected-component analysis for binary fields defined on NESTED HEALPix cells.

Basic usage#

from healpix_analyse import connected_components

labels, n_components = connected_components(
    mask,
    cell_ids,
    refinement_level,
    connectivity="edge",
)

Background cells receive label 0.

Foreground components receive deterministic labels:

1, 2, 3, ...

Component numbering follows the first active cell encountered in the processing-domain order.

Connectivity#

Two HEALPix connectivity definitions are supported.

Edge connectivity#

connectivity="edge"

Cells are connected only when they share a HEALPix cell edge.

This is the HEALPix analogue of Cartesian 4-connectivity.

For a Cartesian raster:

. X .
X C X
. X .

For the HEALPix topology, the four edge-sharing directional neighbours are:

SW, NW, NE, SE

Edge-or-vertex connectivity#

connectivity="edge_or_vertex"

Cells are connected when they share either a HEALPix edge or a HEALPix vertex.

This is the HEALPix analogue of Cartesian 8-connectivity.

For a Cartesian raster:

X X X
X C X
X X X

For the HEALPix topology, the full immediate neighbourhood contains up to eight directional positions:

SW, W, NW, N, NE, E, SE, S

At HEALPix topological special locations, one of the vertex-touching positions may be absent, giving seven distinct immediate neighbours.

NESTED indexing only#

The current implementation supports NESTED HEALPix indexing only.

RING indexing and automatic indexing-scheme detection are intentionally not supported.

Processing domain#

cell_ids defines the cells for which input values are available.

domain defines the cells that participate in the connected-component graph.

labels, n_components = connected_components(
    mask,
    cell_ids,
    refinement_level,
    domain=domain,
)

domain must be a subset of cell_ids.

Cells outside domain are absent from the topology.

For example:

A -- X -- B

if X lies outside the domain, connectivity cannot pass through X, even if its input mask value is active.

Output order follows the exact order supplied by domain.

Component size#

from healpix_analyse import component_size

sizes = component_size(labels)

The returned array is indexed by component label.

For:

labels = [1, 1, 0, 2, 2, 2]

the result is:

sizes = [0, 2, 3]

Background label 0 is assigned size zero.

Component area#

from healpix_analyse import component_area

areas = component_area(
    labels,
    refinement_level,
    ellipsoid="WGS84",
)

HEALPix cells at one refinement level have equal area.

The component area is therefore:

component cell count × HEALPix cell area

For the Sentinel-2 HEALPix processing use case, WGS84 is the intended ellipsoid.

The area computation uses the WGS84 ellipsoid surface area rather than an independently selected spherical-Earth radius.

Remove small components#

Components can be filtered by cell count:

from healpix_analyse import remove_small_components

cleaned = remove_small_components(
    mask,
    cell_ids,
    refinement_level,
    min_cells=4,
    connectivity="edge",
)

or by physical area:

cleaned = remove_small_components(
    mask,
    cell_ids,
    refinement_level,
    min_area_m2=10_000.0,
    connectivity="edge",
    ellipsoid="WGS84",
)

Exactly one of min_cells or min_area_m2 must be supplied.

Threshold semantics#

Component thresholds are inclusive.

component size >= threshold  -> retained
component size < threshold   -> removed

For example, a two-cell component is retained when:

cleaned = remove_small_components(
    mask,
    cell_ids,
    refinement_level,
    min_cells=2,
)

The same rule applies to physical-area thresholds.

Background label 0 always remains background, including when the selected threshold is zero.

Generic Earth Observation example#

Connected-component filtering is useful as a generic post-processing step for binary Earth Observation segmentations.

For example, small isolated regions can be removed from a segmentation mask using a cell-count threshold:

from healpix_analyse import remove_small_components

cleaned = remove_small_components(
    segmentation_mask,
    cell_ids,
    refinement_level,
    min_cells=4,
    connectivity="edge",
)

The same operation can use a physical-area threshold instead:

cleaned = remove_small_components(
    segmentation_mask,
    cell_ids,
    refinement_level,
    min_area_m2=100_000.0,
    connectivity="edge",
    ellipsoid="WGS84",
)

This pattern is generic and can be applied to cloud, snow or ice, water, land-cover, habitat, or other binary segmentation masks.

The library itself does not assign application-specific meanings or class identifiers to the foreground mask.

Topological edge cases#

Connectivity is defined by HEALPix topology rather than geographic coordinate proximity.

As a consequence, connected components work continuously across:

  • HEALPix base-pixel boundaries,

  • polar regions,

  • the longitude coordinate wrap-around,

  • and other HEALPix topological special locations.

No special treatment of the longitude seam or poles is required by the caller.

A component may also touch the boundary of a partial processing domain. Cells outside the domain are simply absent from the connectivity graph; valid foreground cells on the domain boundary remain part of their component.

Background cells may form holes inside a connected foreground region. A hole remains background and does not split the surrounding foreground when an alternative topological path connects that foreground.

NumPy and PyTorch#

NumPy arrays and PyTorch tensors are supported.

For Torch input, outputs are returned on the original device.

Connected-component operations are discrete and are therefore not differentiable.

Temporary topology backend#

Immediate HEALPix topology is currently obtained through a private healpix_analyse._topology helper.

That helper temporarily uses:

healpy.get_all_neighbours(..., nest=True)

That call is a leftover compatibility shim, not the intended design: the rest of the package takes its topology from healpix-geo (nested.neighbours(..., connectivity="all")), and this helper is expected to follow.

The planned final architecture is:

healpix-analyse
      |
      v
private topology helper
      |
      v
healpix-geo
      |
      v
CDSHEALPix

Once direction-aware neighbour access is exposed by healpix-geo, the private backend can be replaced without changing the public connected-component API.