Plots and visualizations

import numpy as np
import matplotlib.pyplot as plt
import multipers as mp
from multipers.data import noisy_annulus
from multipers.filtrations.density import KDE
np.random.seed(1)
X = noisy_annulus(n1=200, n2=200) 
codensity = - (KDE(bandwidth=0.2, return_log=True).fit(X).score_samples(X))
plt.scatter(X[:,0], X[:,1], s=20, c=-codensity);
plt.gca().set_aspect(1);
../_images/28d364d078cb5d13ada7215400b707001cb07c77cb6163db33e5268b11a8c722.png

Rips complex

from multipers.filtrations import RipsLowerstar
st = RipsLowerstar(points=X, function=codensity).collapse_edges(-2).expansion(2)
mma = mp.module_approximation(st)
mma.plot(degree = 1)
../_images/31279573ed72364371b0a937975fb5d0b9961336ded31da238ab26a611b5e1ce.png
from multipers.plots import plot_simplicial_complex
radius = .5
codens = 2.85
plot_simplicial_complex(st,X, radius, codens, mma=mma, degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/0152ca5eb9e96ae6c339d4e935a7ca74481e943815a79a7a1028c7df3403a309.png
from multipers.plots import plot_simplicial_complex
radius = .6
codens = 3
plot_simplicial_complex(st,X, radius, codens, mma=mma, degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/58af5eedb338b9256eb402974e85fc9802875a77b9b63e74de4c32aa1c488e6e.png
from multipers.plots import plot_simplicial_complex
radius = 2.5
codens = 2.4
plot_simplicial_complex(st,X, radius, codens, mma=mma, degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/9ee6d72007b4df8884900a192d0f0a461da4dfd576535cb6466904b1e37f16c2.png
from multipers.plots import plot_simplicial_complex
radius = .5
codens = 2.75
plot_simplicial_complex(st,X, radius, codens, mma=mma, degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/f8cca8699bcdc7141af6772245521391e1e81987ef4864b9b27b51c28e951226.png

Delaunay-Lowerstar

from multipers.filtrations import DelaunayLowerstar
st_delaunay = DelaunayLowerstar(points = X, function=codensity)
mma = mp.module_approximation(st_delaunay)
/tmp/ipykernel_161184/617221178.py:3: UserWarning: (copy warning) Got a non-vine slicer as an input. Use `vineyard=True` to remove this copy.
  mma = mp.module_approximation(st_delaunay)
from multipers.plots import plot_point_cloud
radius = .25
codens = 2.85
plot_point_cloud(X, codensity,radius,codens, mma=mma,degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/8760f7148f2d96bb6668c1dd624631e171c4ca469185f3bd3c05c1376993c1ed.png
from multipers.plots import plot_point_cloud
radius = .6
codens = 2.85
plot_point_cloud(X, codensity,radius,codens, mma=mma,degree=1)
plt.gcf().set_size_inches(9, 4)
../_images/62f7ffa86b293de444625abe742413863652a0d80e8001d759c778ddce898f8e.png

Signed measures

fig, (a,b) = plt.subplots(ncols=2, figsize=(12,5))
plt.sca(a)
sm, = mp.signed_measure(st, degree=1, plot=True, invariant="hilbert");
plt.sca(b)
mp.point_measure.integrate_measure(*sm, plot=True);
../_images/563fbb2e0e27a0ffb68b0e8980642fc093adf09a465904b4ab42fd0b99eff003.png
fig, (a,b) = plt.subplots(ncols=2, figsize=(12,5))
plt.sca(a)
(pts,w), = mp.signed_measure(st_delaunay,  plot=True, invariant="euler");
plt.sca(b)
mp.point_measure.integrate_measure(pts, w, plot=True); # only the positive part here
../_images/bb3141b17e278035eb2f795810212d201b547fbda52f3b853b117c6ca66a15b4.png

Line slices

s = mp.Slicer(st_delaunay).minpres(1)
sm, = mp.signed_measure(
    s.grid_squeeze(strategy="regular_closest", resolution=50),
    plot=True,
    degree=1,
    invariant="rectangle"
);

basepoint= np.asarray([1,4.1])
direction= np.array([.5,1.])
bc = mp.point_measure.barcode_from_rank_sm(sm=sm, basepoint=basepoint, direction=direction)
slope=direction[1]/direction[0]
plt.axline(basepoint,slope=slope,c="k")
for bar in bc:
    bar = basepoint[None] + direction[None]*bar[:,None]
    plt.plot(bar[:,0], bar[:,1], 'ro-', lw=5)
../_images/94f1d56bf7f695089cd56a583443d200601f2543d8f85a5a627f3da2e3b7a8f0.png
sm_hook, = mp.signed_measure(
    s.grid_squeeze(strategy="regular_closest", resolution=50),
    degree=1,
    invariant="hook",
)
mp.plots.plot_signed_measure(sm_hook, alpha=.5)
../_images/787613c1091b47484070f0da80007eecd7ea0d82fb08bfbb8b622c35d8dda3a4.png
from gudhi.wasserstein import wasserstein_distance
bc_ground_truth = s.persistence_on_line(basepoint=basepoint, direction=direction)[1]
print("Bottleneck error:",wasserstein_distance(bc,bc_ground_truth)) # the `grid_squeeze` introduced an error 
Bottleneck error: 0.11974205620221179
mma_delaunay = mp.module_approximation(s)
mma_delaunay.plot(1)
bc2 = mma_delaunay.barcode2(basepoint=basepoint, direction=direction, keep_inf=False)[1]
slope=direction[1]/direction[0]
plt.axline(basepoint,slope=slope,c="k")
for bar in bc2:
    bar = basepoint[None] + direction[None]*bar[:,None]
    plt.plot(bar[:,0], bar[:,1], 'ro-', lw=5)
    
print("Bottleneck error:", wasserstein_distance(bc2, bc_ground_truth))
/tmp/ipykernel_161184/3922999236.py:1: UserWarning: (copy warning) Got a non-vine slicer as an input. Use `vineyard=True` to remove this copy.
  mma_delaunay = mp.module_approximation(s)
Bottleneck error: 0.0007861610342647651
../_images/ba24966bf9aa68caa4cebbae9a7efedcef1a60967ed50f2001f81c3190d22d4f.png