Note
Go to the end to download the full example code.
Submatrix Index Tool
A common pain point in computational homological algebra is passing between matrix and integer indices
for boundary and other matrices. OAT offers a oat_python.core.vietoris_rips.SubmatrixIndexTool
to help wth this.
See also
See the Sparse Matrices gallery for more examples!
Setup
import oat_python as oat
from fractions import Fraction
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import plotly.graph_objects as go
from scipy.sparse import csr_matrix
Generate a point cloud
points = oat.point_cloud.sphere_or_slice(n_points=100)
Plot the point cloud
trace = go.Scatter3d(x=points[:,0],y=points[:,1],z=points[:,2], mode="markers", marker=dict(opacity=1, size=4, color=points[:,2], colorscale="Aggrnyl"))
fig = go.Figure(data=trace)
fig.update_layout(title=dict(text="Point cloud"), height=800,width=850)
fig
Compute persistent homology
We compute persistent homology by factoring the boundary matrix. The following cell generates a sparse distance matrix and feeds it to the persistent homology solver. The result is a decomposition boundary matrix. We will extract information from this matrix in the following cells.
Prepare a dissimilarity matrix
dissimilarity_matrix = oat.dissimilarity.sparse_matrix_for_points(
points = points,
max_dissimilarity = 0.5,
)
Create and decompose the boundary matrix
decomposition = oat.core.vietoris_rips.BoundaryMatrixDecomposition(
dissimilarity_matrix = dissimilarity_matrix,
max_homology_dimension = 1,
)
Access indices
Create a oat_python.core.vietoris_rips.SubmatrixIndexTool whose rows and columns are the vertices and edges of the Vietoris-Rips complex, respectively.
submatrix_index_tool = decomposition.submatrix_index_tool(
row_dimensions = [0,],
column_dimensions = [1,]
)
submatrix_index_tool
<SubmatrixIndexTool: 100 row indices, 292 column indices>
The number of row and column indices can be accessed via lookup functions:
submatrix_index_tool.number_of_rows()
100
submatrix_index_tool.number_of_columns()
292
The (ordered) lists of row and column indices can also be exported to dataframe format, for inspection:
oat.plot.display_dataframes_side_by_side(
submatrix_index_tool.row_indices()[:5],
submatrix_index_tool.column_indices()[:5],
titles=["Row indices (vertices)","Column indices (edges)"]
)
Write a submatrix to CSR
A common task in data analysis is to export a submatrix of the boundary matrix into standard Python sparse matrix format, such as SciPy’s CSR. In order to do this, you have to specify which rows and columns you want, and in what order. The oat_python.core.vietoris_rips.SubmatrixIndexTool lets you specify these criteria exactly.
boundary_matrix = decomposition.boundary_matrix_oracle()
boundary_submatrix = boundary_matrix.write_submatrix_to_csr(
submatrix_index_tool
)
boundary_submatrix
<100x292 sparse matrix of type '<class 'numpy.float64'>'
with 584 stored elements in Compressed Sparse Row format>
plt.figure(figsize=(6, 6))
plt.spy(boundary_submatrix, markersize=2, color="orange")
plt.title(r'Boundary Matrix ($\partial_1$)', y=-0.18) # Move title to the bottom
plt.tight_layout()

/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_fontconfig_pattern.py:85: PyparsingDeprecationWarning: 'parseString' deprecated - use 'parse_string'
parse = parser.parseString(pattern)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_fontconfig_pattern.py:89: PyparsingDeprecationWarning: 'resetCache' deprecated - use 'reset_cache'
parser.resetCache()
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2010: PyparsingDeprecationWarning: 'oneOf' deprecated - use 'one_of'
p.space = oneOf(self._space_widths)("space")
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2012: PyparsingDeprecationWarning: 'oneOf' deprecated - use 'one_of'
p.style_literal = oneOf(
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2015: PyparsingDeprecationWarning: 'leaveWhitespace' deprecated - use 'leave_whitespace'
p.symbol = Regex(
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2024: PyparsingDeprecationWarning: 'oneOf' deprecated - use 'one_of'
p.start_group = Optional(r"\math" + oneOf(self._fontnames)("font")) + "{"
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2027: PyparsingDeprecationWarning: 'oneOf' deprecated - use 'one_of'
p.delim = oneOf(self._delims)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:1984: PyparsingDeprecationWarning: 'setName' deprecated - use 'set_name'
val.setName(key)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:1987: PyparsingDeprecationWarning: 'setParseAction' deprecated - use 'set_parse_action'
val.setParseAction(getattr(self, key))
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:1748: PyparsingDeprecationWarning: 'setParseAction' deprecated - use 'set_parse_action'
return Empty().setParseAction(raise_error)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2088: PyparsingDeprecationWarning: 'endQuoteChar' argument is deprecated, use 'end_quote_char'
p.text = cmd(r"\text", QuotedString('{', '\\', endQuoteChar="}"))
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2097: PyparsingDeprecationWarning: 'oneOf' deprecated - use 'one_of'
+ OneOrMore(oneOf(["_", "^"]) - p.placeable)("subsuper")
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2146: PyparsingDeprecationWarning: 'unquoteResults' argument is deprecated, use 'unquote_results'
p.math_string = QuotedString('$', '\\', unquoteResults=False)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2147: PyparsingDeprecationWarning: 'leaveWhitespace' deprecated - use 'leave_whitespace'
p.non_math = Regex(r"(?:(?:\\[$])|[^$])*").leaveWhitespace()
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2170: PyparsingDeprecationWarning: 'parseString' deprecated - use 'parse_string'
result = self._expression.parseString(s)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2197: PyparsingDeprecationWarning: 'parseString' deprecated - use 'parse_string'
return self._math_expression.parseString(toks[0][1:-1], parseAll=True)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/pyparsing/util.py:466: PyparsingDeprecationWarning: 'parseAll' argument is deprecated, use 'parse_all'
return fn(self, *args, **kwargs)
/home/docs/checkouts/readthedocs.org/user_builds/oat-python/envs/latest/lib/python3.9/site-packages/matplotlib/_mathtext.py:2178: PyparsingDeprecationWarning: 'resetCache' deprecated - use 'reset_cache'
ParserElement.resetCache()
Change index types
Get a row vector from the CSR matrix
# Right now we have to convert row coefficients to fractions, but in the future this will be taken care of automatically
row_vector = boundary_submatrix[0].toarray().flatten()
row_vector = np.vectorize(Fraction.from_float)(row_vector)
row_vector[:10]
array([Fraction(-1, 1), Fraction(0, 1), Fraction(0, 1), Fraction(-1, 1),
Fraction(0, 1), Fraction(0, 1), Fraction(0, 1), Fraction(0, 1),
Fraction(0, 1), Fraction(0, 1)], dtype=object)
Convert integer indices to simplex indices:
chain = submatrix_index_tool.row_vector_dataframe_for_dense_array(
row_vector
)
chain
Total running time of the script: (0 minutes 0.228 seconds)