Python API Guide
This page summarizes the current public Python interface. The package name is
morseframes, usually imported as:
import morseframes as mf
The Python package uses the native C++ backend when _morse_core is available
and falls back to a pure-Python implementation otherwise.
print(mf.__version__)
print(mf.cpp_backend_available())
To force the pure-Python fallback:
MORSEFRAMES_DISABLE_CPP_BACKEND=1 python3 script.py
Complexes
The main input type is FilteredComplex, a finite filtered abstract simplicial
complex with contiguous simplex ids.
complex_ = mf.FilteredComplex.from_simplices([
([0], 0.0),
([1], 0.0),
([0, 1], 1.0),
])
Useful constructors:
mf.FilteredComplex.from_simplices(items)
mf.FilteredComplex.from_facets(facets, filtration=...)
mf.FilteredComplex.from_lower_star(facets, vertex_values, dimension_offset=0.0)
mf.FilteredComplex.from_graph(num_vertices, edges, vertex_filtration=..., edge_filtration=...)
mf.FilteredComplex.from_rips_distance_matrix(distances, threshold=..., max_dimension=...)
mf.FilteredComplex.from_gudhi_simplex_tree(simplex_tree)
Useful queries:
complex_.size
complex_.num_levels
complex_.dimension(simplex_id)
complex_.filtration(simplex_id)
complex_.vertices(simplex_id)
complex_.simplex_id([0, 1])
[0, 1] in complex_
complex_.boundary(simplex_id)
complex_.coboundary(simplex_id)
complex_.boundary_simplices([0, 1, 2])
complex_.coboundary_simplices([0, 1])
For incremental construction, use SimplexTreeBuilder:
builder = mf.SimplexTreeBuilder()
builder.insert([0, 1, 2], 2.0, include_faces=True)
complex_ = builder.finalize()
Sequence Strategies
Most high-level functions accept an algorithm keyword. The currently exposed
strategies are:
"saturated"
"f-max"
"f-min"
"same-level-reduction"
"plateau-greedy"
"flooding-max"
"flooding-min"
"flooding-minmax"
"flooding-maxmin"
The default is "saturated".
Flooding strategies are filtration-monotone F-sequences: after the sequence
has reached a filtration value, it does not return to a lower value. The
saturated, same-level-reduction, plateau-greedy, and flooding-*
strategies have this form. The f-max and f-min strategies are global
seed-and-expand F-sequence builders; they keep regular pairs inside one
filtration level, but they are not required to be flooding.
Morse Sequences
Compute a Morse sequence:
sequence = mf.compute_morse_sequence(complex_, algorithm="f-max")
Important fields and helpers:
sequence.steps
sequence.critical_simplices
sequence.paired_with
sequence.critical_index(simplex_id)
sequence.steps_as_simplices(complex_)
sequence.critical_simplices_as_simplices(complex_)
Each step is either "critical" or "regular_pair".
Reference And Coreference Maps
Reference maps and coreference maps are annotation tables indexed by simplex id. An annotation is a tuple of critical labels. Use the simplex helpers to convert labels back to simplex vertex tuples.
references = mf.compute_reference_map(complex_, sequence)
coreferences = mf.compute_coreference_map(complex_, sequence)
reference_simplices = mf.reference_map_as_simplices(complex_, sequence, references)
coreference_simplices = mf.coreference_map_as_simplices(complex_, sequence, coreferences)
The sequence and reference map can be computed in one pass:
frame = mf.compute_morse_sequence_and_reference_map(complex_, algorithm="f-max")
sequence = frame.sequence
references = frame.references
The dual coreference frame is also available:
dual_frame = mf.compute_morse_sequence_and_coreference_map(
complex_,
algorithm="same-level-reduction",
)
coreferences = dual_frame.coreferences
Morse Complexes
The Morse complex is represented on critical simplex ids.
morse_complex = mf.compute_morse_complex(complex_, sequence, references)
Useful fields and helpers:
morse_complex.critical_simplices
morse_complex.boundary(critical_id)
morse_complex.boundary_as_simplices(complex_, critical_id)
The reference and coreference complexes can also be computed explicitly:
reference_complex = mf.compute_reference_complex(complex_, sequence, references)
coreference_complex = mf.compute_coreference_complex(complex_, sequence, coreferences)
Persistence
The main entry point is:
diagram = mf.compute_morse_persistence(
complex_,
sequence=sequence,
references=references,
)
If no sequence or reference map is supplied, they are computed internally:
diagram = mf.compute_morse_persistence(complex_, algorithm="f-min")
The result is a PersistenceDiagram:
diagram.finite_pairs
diagram.essential
diagram.finite_barcode()
diagram.finite_barcode(include_zero=True)
diagram.essential_barcode()
diagram.intervals_as_simplices(complex_)
Ordinary full-complex persistence is available as a validation baseline:
standard = mf.compute_standard_persistence(complex_)
assert diagram.finite_barcode() == standard.finite_barcode()
assert diagram.essential_barcode() == standard.essential_barcode()
Prime Fields
Persistence over a prime field F_p is available by passing modulus=p.
Composite moduli are rejected.
diagram_f3 = mf.compute_morse_persistence(
complex_,
algorithm="f-max",
modulus=3,
)
standard_f3 = mf.compute_standard_persistence(complex_, modulus=3)
Explicit signed mod-p reference and coreference maps are also exposed:
references_f3 = mf.compute_reference_map_modp(complex_, sequence, modulus=3)
diagram_f3 = mf.compute_morse_persistence_modp(
complex_,
sequence=sequence,
references=references_f3,
modulus=3,
)
Profiling And Selection
The profiling API builds the Morse sequence and compact reference-reduction input without running the full pivot reduction.
profile = mf.profile_morse_reference_frame(complex_, algorithm="f-max")
print(profile.critical_ratio)
print(profile.estimated_reducer_work)
To compare strategies:
profiles = mf.profile_morse_sequence_algorithms(
complex_,
algorithms=("saturated", "f-max", "f-min", "same-level-reduction"),
)
best = mf.select_morse_sequence_profile(
complex_,
selection_metric="profile_total_work",
)
For a measured, timing-based comparison:
benchmarks = mf.benchmark_sequence_algorithms(
complex_,
algorithms=("saturated", "f-max", "f-min"),
repeats=3,
)
The adaptive entry point can choose between Morse persistence and ordinary persistence:
result = mf.compute_persistence_adaptive(
complex_,
sequence_algorithm="auto",
)
print(result.method)
print(result.finite_barcode())
Plotting Helpers
Plotly helpers live in morseframes.plotting.
from morseframes import plotting
field = plotting.build_noisy_sine_square(size=12, noise=0.05, seed=0)
fig = plotting.plot_morse_surface_with_persistence(field, algorithm="f-max")
fig.show()
Plotly is optional and can be installed with:
python3 -m pip install "morseframes[plotting]==0.1.0a2"