CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-h3

Python bindings for H3, a hierarchical hexagonal geospatial indexing system

84

0.95x
Overview
Eval results
Files

cell-hierarchy.mddocs/

Cell Hierarchy

Operations for working with H3's hierarchical structure, including parent-child relationships, cell compaction, and resolution changes. H3's multi-resolution hierarchy enables efficient storage and analysis across different scales.

Capabilities

Parent-Child Relationships

Navigate up and down the hierarchical structure between different resolution levels.

def cell_to_parent(h: str, res: int = None) -> str:
    """
    Get the parent cell at a coarser resolution.
    
    Args:
        h: H3 cell identifier
        res: Target parent resolution. If None, uses resolution(h) - 1
        
    Returns:
        Parent H3 cell identifier at target resolution
        
    Raises:
        H3CellInvalidError: If h is not a valid H3 cell
        H3ResDomainError: If res < 0 or res >= resolution(h)
        
    Note:
        Parent resolution must be coarser (lower number) than child.
        Each cell has exactly one parent at each coarser resolution.
    """

def cell_to_children(h: str, res: int = None) -> list[str]:
    """
    Get all child cells at a finer resolution.
    
    Args:
        h: H3 cell identifier  
        res: Target child resolution. If None, uses resolution(h) + 1
        
    Returns:
        List of child H3 cell identifiers at target resolution
        
    Raises:
        H3CellInvalidError: If h is not a valid H3 cell
        H3ResDomainError: If res > 15 or res <= resolution(h)
        
    Note:
        Child resolution must be finer (higher number) than parent.
        Most cells have 7 children, but some have different counts due to
        the spherical geometry and pentagon locations.
    """

def cell_to_children_size(h: str, res: int = None) -> int:
    """
    Get the count of child cells at a finer resolution.
    
    Args:
        h: H3 cell identifier
        res: Target child resolution. If None, uses resolution(h) + 1
        
    Returns:
        Number of child cells at target resolution
        
    Raises:
        H3CellInvalidError: If h is not a valid H3 cell
        H3ResDomainError: If res > 15 or res <= resolution(h)
        
    Note:
        More efficient than len(cell_to_children(h, res)) for large child counts.
    """

def cell_to_center_child(h: str, res: int = None) -> str:
    """
    Get the center child cell at a finer resolution.
    
    The center child is the child cell whose center is closest to
    the parent cell's center.
    
    Args:
        h: H3 cell identifier
        res: Target child resolution. If None, uses resolution(h) + 1
        
    Returns:
        Center child H3 cell identifier
        
    Raises:
        H3CellInvalidError: If h is not a valid H3 cell
        H3ResDomainError: If res > 15 or res <= resolution(h)
    """

Child Positioning

Work with child position indices within parent cells.

def cell_to_child_pos(child: str, res_parent: int) -> int:
    """
    Get the position index of a child cell within its parent.
    
    Args:
        child: Child H3 cell identifier
        res_parent: Resolution of the parent cell
        
    Returns:
        Integer position index of child relative to parent
        
    Raises:
        H3CellInvalidError: If child is not a valid H3 cell
        H3ResDomainError: If res_parent >= resolution(child)
        
    Note:
        Position indices are stable: the same child always has the same
        position within its parent across different operations.
    """

def child_pos_to_cell(parent: str, res_child: int, child_pos: int) -> str:
    """
    Get a specific child cell by position index.
    
    Args:
        parent: Parent H3 cell identifier
        res_child: Resolution of desired child cell
        child_pos: Position index of desired child
        
    Returns:
        Child H3 cell identifier at specified position
        
    Raises:
        H3CellInvalidError: If parent is not a valid H3 cell
        H3ResDomainError: If res_child <= resolution(parent) or res_child > 15
        ValueError: If child_pos is outside valid range for this parent
        
    Note:
        Valid child_pos range is 0 to cell_to_children_size(parent, res_child) - 1.
    """

Cell Compaction

Optimize cell collections by combining child cells into parents where possible.

def compact_cells(cells: list[str]) -> list[str]:
    """
    Compact a collection of cells by combining children into parents.
    
    When all children of a parent cell are present in the input collection,
    they are replaced by their parent cell. This process continues recursively
    up the hierarchy until no further compaction is possible.
    
    Args:
        cells: Collection of H3 cell identifiers (must all be same resolution)
        
    Returns:
        Compacted list of H3 cell identifiers (mixed resolutions)
        
    Raises:
        H3ResMismatchError: If input cells have different resolutions
        H3CellInvalidError: If any cell identifier is invalid
        
    Note:
        Input cells must all be at the same resolution.
        Output may contain cells at various resolutions.
        Compaction reduces storage and improves query performance.
    """

def uncompact_cells(cells: list[str], res: int) -> list[str]:
    """
    Expand a collection of cells to a uniform resolution.
    
    All cells in the collection are expanded to their children at the
    target resolution. This reverses the compact_cells operation.
    
    Args:
        cells: Collection of H3 cell identifiers (mixed resolutions allowed)
        res: Target resolution for all output cells
        
    Returns:
        List of H3 cell identifiers all at target resolution
        
    Raises:
        H3ResDomainError: If res > 15
        H3CellInvalidError: If any cell identifier is invalid
        ValueError: If any input cell has resolution > res
        
    Note:
        All input cells must have resolution <= target resolution.
        Output cells provide complete coverage of input area at uniform resolution.
    """

System Introspection

Get information about cells at specific resolutions and system structure.

def get_res0_cells() -> list[str]:
    """
    Get all H3 cells at resolution 0 (base cells).
    
    Returns:
        List of all 122 base H3 cells covering the Earth
        
    Note:
        These are the coarsest cells in the H3 system.
        All other cells are descendants of these base cells.
        Order is not guaranteed.
    """

def get_pentagons(res: int) -> list[str]:
    """
    Get all pentagon cells at a given resolution.
    
    Args:
        res: H3 resolution (0-15)
        
    Returns:
        List of all 12 pentagon H3 cells at the specified resolution
        
    Raises:
        H3ResDomainError: If res < 0 or res > 15
        
    Note:
        There are exactly 12 pentagons at every resolution level.
        All other cells at that resolution are hexagons.
        Pentagons occur at the 12 vertices of the icosahedron.
    """

Usage Examples

Basic Parent-Child Navigation

import h3

# Start with a high-resolution cell
child_cell = h3.latlng_to_cell(37.7749, -122.4194, 9)
print(f"Child cell (res 9): {child_cell}")
print(f"Resolution: {h3.get_resolution(child_cell)}")

# Get parent at resolution 7
parent = h3.cell_to_parent(child_cell, res=7)
print(f"Parent cell (res 7): {parent}")

# Get all children of the parent back at resolution 9
children = h3.cell_to_children(parent, res=9)
print(f"Parent has {len(children)} children at resolution 9")
print(f"Original child in children: {child_cell in children}")  # True

# Get just the center child
center_child = h3.cell_to_center_child(parent, res=9)
print(f"Center child: {center_child}")
print(f"Center child is original: {center_child == child_cell}")

Multi-Level Hierarchy

import h3

# Trace a cell through multiple resolution levels
original = h3.latlng_to_cell(51.5074, -0.1278, 10)  # London, res 10

print("Hierarchy from coarse to fine:")
current = original

# Go up to resolution 0
while h3.get_resolution(current) > 0:
    parent = h3.cell_to_parent(current)
    res = h3.get_resolution(parent)
    print(f"  Resolution {res}: {parent}")
    current = parent

print(f"  Resolution 0: {current} (base cell)")

# Go back down showing child counts
current = h3.cell_to_parent(original, res=5)  # Start from res 5
print(f"\nChild expansion from resolution 5:")

for target_res in range(6, 11):
    children = h3.cell_to_children(current, res=target_res)
    print(f"  Res {target_res}: {len(children)} children")
    
    # For next iteration, use the center child
    if target_res < 10:
        current = h3.cell_to_center_child(current, res=target_res)

Child Positioning

import h3

# Work with child positions
parent = h3.latlng_to_cell(40.7589, -73.9851, 6)  # NYC, res 6
children = h3.cell_to_children(parent)

print(f"Parent: {parent}")
print(f"Children ({len(children)}):")

# Show each child with its position
positions = []
for child in children:
    pos = h3.cell_to_child_pos(child, res_parent=6)
    positions.append((child, pos))
    print(f"  Position {pos}: {child}")

# Sort by position and verify we can reconstruct
positions.sort(key=lambda x: x[1])
print(f"\nReconstructing children by position:")

for child, pos in positions:
    reconstructed = h3.child_pos_to_cell(parent, res_child=7, child_pos=pos)
    print(f"  Position {pos}: {reconstructed} (matches: {child == reconstructed})")

Cell Compaction

import h3
import random

# Create a region with some complete families of children
center = h3.latlng_to_cell(37.7749, -122.4194, 6)
region_cells = h3.grid_disk(center, k=2)  # Get area around center

# Expand all to resolution 8
expanded = h3.uncompact_cells(region_cells, res=8)
print(f"Original region: {len(region_cells)} cells at res 6")
print(f"Expanded region: {len(expanded)} cells at res 8")

# Add some random cells at resolution 8 to create incomplete families
random_cells = []
for _ in range(20):
    lat = 37.7749 + random.uniform(-0.1, 0.1)
    lng = -122.4194 + random.uniform(-0.1, 0.1)
    cell = h3.latlng_to_cell(lat, lng, 8)
    random_cells.append(cell)

all_cells = expanded + random_cells
print(f"With random additions: {len(all_cells)} cells")

# Compact back down
compacted = h3.compact_cells(all_cells)
print(f"After compaction: {len(compacted)} cells")

# Verify coverage is preserved by expanding back
verification = h3.uncompact_cells(compacted, res=8)
original_set = set(all_cells)
verification_set = set(verification)

print(f"Coverage preserved: {original_set == verification_set}")
print(f"Compression ratio: {len(compacted) / len(all_cells):.2f}")

Pentagon Analysis

import h3

# Analyze pentagons across resolutions
print("Pentagon analysis:")
for res in range(0, 6):
    pentagons = h3.get_pentagons(res)
    print(f"Resolution {res}: {len(pentagons)} pentagons")
    
    # Show some pentagon properties
    pentagon = pentagons[0]  # Pick first pentagon
    neighbors = h3.grid_ring(pentagon, k=1)
    
    print(f"  Example pentagon {pentagon}:")
    print(f"    Has {len(neighbors)} neighbors (vs 6 for hexagons)")
    print(f"    Boundary has {len(h3.cell_to_boundary(pentagon))} vertices")

# Find pentagon children behavior
res0_pentagon = h3.get_pentagons(0)[0]
children = h3.cell_to_children(res0_pentagon, res=1)
print(f"\nResolution 0 pentagon has {len(children)} children at res 1")

# Compare to a hexagon at res 0
res0_cells = h3.get_res0_cells()
res0_hexagons = [cell for cell in res0_cells if not h3.is_pentagon(cell)]
hexagon = res0_hexagons[0]
hex_children = h3.cell_to_children(hexagon, res=1)
print(f"Resolution 0 hexagon has {len(hex_children)} children at res 1")

Base Cell Analysis

import h3

# Analyze the base H3 system structure
base_cells = h3.get_res0_cells()
print(f"Total base cells: {len(base_cells)}")

pentagon_count = sum(1 for cell in base_cells if h3.is_pentagon(cell))
hexagon_count = len(base_cells) - pentagon_count

print(f"  Pentagons: {pentagon_count}")
print(f"  Hexagons: {hexagon_count}")

# Show base cell numbers
print(f"\nBase cell number range:")
base_numbers = [h3.get_base_cell_number(cell) for cell in base_cells]
print(f"  Min: {min(base_numbers)}")
print(f"  Max: {max(base_numbers)}")
print(f"  Unique count: {len(set(base_numbers))}")

# Verify all base cells are resolution 0
resolutions = [h3.get_resolution(cell) for cell in base_cells]
print(f"\nAll resolution 0: {all(res == 0 for res in resolutions)}")

# Show some base cell coverage
print(f"\nSample base cells with centers:")
for i, cell in enumerate(base_cells[:5]):
    lat, lng = h3.cell_to_latlng(cell)
    is_pent = "pentagon" if h3.is_pentagon(cell) else "hexagon"
    base_num = h3.get_base_cell_number(cell)
    print(f"  Base {base_num}: {cell} -> {lat:.1f}, {lng:.1f} ({is_pent})")

Install with Tessl CLI

npx tessl i tessl/pypi-h3

docs

advanced-operations.md

cell-hierarchy.md

core-cell-operations.md

directed-edges.md

grid-navigation.md

index.md

measurements.md

polygon-operations.md

tile.json