Computational topology and topological data analysis library providing state-of-the-art algorithms for constructing simplicial complexes and computing persistent homology
—
Specialized functionality for working with cubical complexes, particularly useful for image analysis, structured grid data, and applications where the data naturally lives on a regular lattice structure.
Main class for constructing and analyzing cubical complexes from bitmap/image data with support for various boundary conditions.
class CubicalComplex:
def __init__(self, dimensions, top_dimensional_cells, periodic_dimensions=None):
"""
Initialize cubical complex from grid data.
Parameters:
- dimensions: List of dimensions for each axis
- top_dimensional_cells: Flattened array of cell values
- periodic_dimensions: List of dimensions with periodic boundary conditions
"""
def persistence(self, homology_coeff_field: int = 11, min_persistence: float = 0.0):
"""
Compute persistent homology of the cubical complex.
Parameters:
- homology_coeff_field: Coefficient field for homology computation
- min_persistence: Minimum persistence value to return
Returns:
list: Persistence pairs as (dimension, (birth, death)) tuples
"""
def cofaces_of_persistence_pairs(self):
"""
Get representative cofaces for persistence pairs.
Returns:
list: Coface representatives for each persistence pair
"""
def vertices_of_persistence_pairs(self):
"""
Get vertex representatives for persistence pairs.
Returns:
list: Vertex representatives for each persistence pair
"""
def num_simplices(self):
"""
Get total number of cubes in the complex.
Returns:
int: Number of cubes
"""
def dimension(self):
"""
Get dimension of the cubical complex.
Returns:
int: Complex dimension
"""
def betti_numbers(self):
"""
Compute Betti numbers.
Returns:
list: Betti numbers for each dimension
"""
def persistent_betti_numbers(self, from_value: float, to_value: float):
"""
Compute persistent Betti numbers within filtration range.
Parameters:
- from_value: Start of filtration range
- to_value: End of filtration range
Returns:
list: Persistent Betti numbers
"""Cubical complexes with periodic boundary conditions, useful for analyzing data on tori and other periodic domains.
class PeriodicCubicalComplex:
def __init__(self, dimensions, top_dimensional_cells):
"""
Initialize periodic cubical complex.
Parameters:
- dimensions: List of dimensions for each axis
- top_dimensional_cells: Flattened array of cell values
"""
def persistence(self, homology_coeff_field: int = 11, min_persistence: float = 0.0):
"""
Compute persistent homology with periodic boundary conditions.
Parameters:
- homology_coeff_field: Coefficient field for homology computation
- min_persistence: Minimum persistence value to return
Returns:
list: Persistence pairs
"""
def cofaces_of_persistence_pairs(self):
"""Get coface representatives for persistence pairs."""
def vertices_of_persistence_pairs(self):
"""Get vertex representatives for persistence pairs."""
def num_simplices(self):
"""Get number of cubes in the complex."""
def dimension(self):
"""Get complex dimension."""Utilities for reading and writing cubical complex data in various formats.
def read_cubical_complex_from_perseus_file(filename: str):
"""
Read cubical complex from Perseus file format.
Parameters:
- filename: Path to Perseus file
Returns:
CubicalComplex: Loaded cubical complex
"""
def write_cubical_complex_to_perseus_file(complex, filename: str):
"""
Write cubical complex to Perseus file format.
Parameters:
- complex: CubicalComplex to save
- filename: Output file path
"""import gudhi
import numpy as np
from PIL import Image
# Load and process image
img = Image.open('example.png').convert('L') # Convert to grayscale
img_array = np.array(img)
# Create cubical complex from image
dimensions = list(img_array.shape)
top_cells = img_array.flatten().astype(float)
cubical_complex = gudhi.CubicalComplex(
dimensions=dimensions,
top_dimensional_cells=top_cells
)
# Compute persistence
persistence = cubical_complex.persistence()
# Visualize results
gudhi.plot_persistence_diagram(persistence)import gudhi
import numpy as np
# Create 3D volume data (e.g., from medical imaging)
volume = np.random.random((50, 50, 50)) # Example random volume
# Create 3D cubical complex
dimensions = [50, 50, 50]
top_cells = volume.flatten()
cubical_complex = gudhi.CubicalComplex(
dimensions=dimensions,
top_dimensional_cells=top_cells
)
# Compute persistence
persistence = cubical_complex.persistence()
# Get representative cofaces
cofaces = cubical_complex.cofaces_of_persistence_pairs()
print(f"Found {len(persistence)} persistence pairs")
print(f"Complex dimension: {cubical_complex.dimension()}")
print(f"Number of cubes: {cubical_complex.num_simplices()}")import gudhi
import numpy as np
# Create data with periodic structure (e.g., wrapping texture)
size = 64
data = np.sin(np.linspace(0, 4*np.pi, size))
data_2d = np.outer(data, data) # Create 2D periodic pattern
# Analyze with periodic cubical complex
periodic_complex = gudhi.PeriodicCubicalComplex(
dimensions=[size, size],
top_dimensional_cells=data_2d.flatten()
)
# Compute persistence with periodic boundaries
periodic_persistence = periodic_complex.persistence()
# Compare with non-periodic analysis
regular_complex = gudhi.CubicalComplex(
dimensions=[size, size],
top_dimensional_cells=data_2d.flatten()
)
regular_persistence = regular_complex.persistence()
print(f"Periodic persistence pairs: {len(periodic_persistence)}")
print(f"Regular persistence pairs: {len(regular_persistence)}")import gudhi
import numpy as np
from scipy import ndimage
# Load image and create multi-scale representation
img = np.random.random((100, 100)) # Example image
# Apply Gaussian filtering at different scales
scales = [1.0, 2.0, 4.0, 8.0]
persistence_at_scales = []
for scale in scales:
# Filter image
filtered_img = ndimage.gaussian_filter(img, sigma=scale)
# Create cubical complex
cubical = gudhi.CubicalComplex(
dimensions=list(filtered_img.shape),
top_dimensional_cells=filtered_img.flatten()
)
# Compute persistence
persistence = cubical.persistence()
persistence_at_scales.append(persistence)
print(f"Scale {scale}: {len(persistence)} persistence pairs")
# Analyze how persistence changes across scales
for i, (scale, pers) in enumerate(zip(scales, persistence_at_scales)):
# Extract 1D persistence intervals
intervals_1d = [interval for dim, interval in pers if dim == 1]
if intervals_1d:
avg_persistence = np.mean([death - birth for birth, death in intervals_1d if death != float('inf')])
print(f"Scale {scale}: Average 1D persistence = {avg_persistence:.3f}")Install with Tessl CLI
npx tessl i tessl/pypi-gudhi