### Load Libraries and Setup Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Imports necessary libraries for data generation, plotting, and persistent homology computation. Ensures that code changes are automatically reloaded. ```python %load_ext autoreload %autoreload 2 import time import matplotlib.pyplot as plt import tadasets from persim import plot_diagrams, bottleneck from ripser import ripser ``` -------------------------------- ### Install Ripser.py Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md Install Ripser.py and its dependency Cython using pip. Ensure Cython is installed first. ```bash pip install Cython pip install Ripser ``` -------------------------------- ### Install Ripser.py locally with verbose output Source: https://github.com/scikit-tda/ripser.py/blob/master/README.md Install a local, editable version of Ripser.py after cloning the repository. Use the -v flag for verbose output to confirm robinhood hashing is detected. ```bash pip install -v . ``` -------------------------------- ### Install Ripser.py using pip Source: https://github.com/scikit-tda/ripser.py/blob/master/README.md Use this command to install the Ripser.py package from PyPI. It includes wheels for all major platforms. ```bash pip install ripser ``` -------------------------------- ### Compile Ripser.py from Source Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md Clone the Ripser.py repository, navigate to the directory, and install it using pip in editable mode. This is useful for development or when using the latest unreleased features. ```bash git clone https://github.com/scikit-tda/ripser.py cd ripser.py pip install -e . ``` -------------------------------- ### Compute Persistence Diagrams with Ripser Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/reference/stubs/ripser.ripser.md This example demonstrates how to compute persistence diagrams from a dataset of circles using the ripser function. It then visualizes these diagrams using plot_diagrams from the persim library. ```python from ripser import ripser, plot_dgms from sklearn import datasets from persim import plot_diagrams data = datasets.make_circles(n_samples=110)[0] dgms = ripser(data)['dgms'] plot_diagrams(dgms, show = True) ``` -------------------------------- ### Generate Torus Loop and Compute Homology (2:1 ratio) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Moebius Strip And The Field of Coefficients.ipynb Generates a loop on a torus with a 2:1 ratio of revolutions around the small and large circles, then computes persistent homology using $\mathbb{Z}/2$ and $\mathbb{Z}/3$ coefficients. This setup is used to visualize the generated loop and its corresponding persistence diagrams. ```python ## Step 1: Setup curve N = 100 # Number of points to sample R = 4 # Big radius of torus r = 1 # Little radius of torus X = np.zeros((N, 3)) t = np.linspace(0, 2 * np.pi, N) X[:, 0] = (R + r * np.cos(2 * t)) * np.cos(t) X[:, 1] = (R + r * np.cos(2 * t)) * np.sin(t) X[:, 2] = r * np.sin(2 * t) ## Step 2: Compute persistent homology dgms2 = ripser(X, coeff=2ization["dgms"] dgms3 = ripser(X, coeff=3ization["dgms"]) fig = plt.figure(figsize=(9, 3)) ax = fig.add_subplot(131, projection="3d") ax.scatter(X[:, 0], X[:, 1], X[:, 2]) ax.set_aspect("equal") plt.title("Generated Loop") plt.subplot(132) plot_diagrams(dgms2) plt.title("$\mathbb{Z} / 2$") plt.subplot(133) plot_diagrams(dgms3) plt.title("$\mathbb{Z} / 3$") plt.tight_layout() plt.show() ``` -------------------------------- ### Initialize and Transform Data with Rips Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/reference/stubs/ripser.Rips.md Demonstrates initializing the Rips class and transforming a dataset to compute persistence diagrams. The plot() method visualizes the results. ```python from ripser import Rips import tadasets data = tadasets.dsphere(n=110, d=2)[0] rips = Rips() rips.transform(data) rips.plot() ``` -------------------------------- ### Generate Point Cloud and Compute Full Filtration Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Sets up a point cloud using tadasets.infty_sign and computes the full rips filtration to establish a baseline for comparison, timing the operation. ```python X = tadasets.infty_sign(n=2000, noise=0.1) plt.scatter(X[:, 0], X[:, 1]) tic = time.time() resultfull = ripser(X) toc = time.time() timefull = toc - tic print( "Elapsed Time: %.3g seconds, %i Edges added" % (timefull, resultfull["num_edges"]) ) ``` -------------------------------- ### Generate Sample Data Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Creates a sample dataset by combining two sets of 100 points each, generated from a 'make_circles' function. This data is used for demonstrating Ripser's functionality. ```python data = ( datasets.make_circles(n_samples=100)[0] + 5 * datasets.make_circles(n_samples=100)[0] ) ``` -------------------------------- ### Import Necessary Libraries Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Imports the core Ripser library, the plotting utility from persim, matplotlib for plotting, and datasets from scikit-learn for generating sample data. ```python from ripser import ripser from persim import plot_diagrams import matplotlib.pyplot as plt from sklearn import datasets ``` -------------------------------- ### Visualize Original and Subsampled Data with Persistence Diagrams Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Plots the original and subsampled point clouds, along with their respective persistence diagrams, for visual comparison. This helps in assessing the quality of the approximation. ```python plt.figure(figsize=(12, 12)) plt.subplot(221) plt.scatter(X[:, 0], X[:, 1]) plt.title("Original Point Cloud (%i Points)" % (X.shape[0])) plt.axis("equal") plt.subplot(222) plt.scatter(X[idx_perm, 0], X[idx_perm, 1]) plt.title("Subsampled Cloud (%i Points)" % (idx_perm.size)) plt.axis("equal") plt.subplot(223) plot_diagrams(dgms_full) plt.title("Original point cloud diagrams") plt.subplot(224) plot_diagrams(dgms_sub) plt.title("Subsampled point diagrams") plt.show() ``` -------------------------------- ### Compile Ripser.py with Robin Hood Hashmap Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md To enable performance optimizations, clone the robin-hood-hashing library into the ripser/robinhood directory before compiling Ripser.py from source. ```bash git clone https://github.com/martinus/robin-hood-hashing ripser/robinhood ``` -------------------------------- ### ripser.Rips Class Initialization Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/reference/stubs/ripser.Rips.md Initializes the Rips class with various parameters to control the persistence computation. ```APIDOC ## ripser.Rips ### Description sklearn style class interface for `ripser` with `fit` and `transform` methods. ### Parameters #### Initialization Parameters - **maxdim** (int, optional, default 1) - Maximum homology dimension computed. Will compute all dimensions lower than and equal to this value. For 1, H_0 and H_1 will be computed. - **thresh** (float, optional, default infinity) - Maximum distances considered when constructing filtration. If infinity, compute the entire filtration. - **coeff** (int prime, optional, default 2) - Compute homology with coefficients in the prime field Z/pZ for p=coeff. - **do_cocycles** (bool, optional) - Indicator of whether to compute cocycles, if so, we compute and store cocycles in the cocycles_ dictionary Rips member variable. - **n_perm** (int, optional) - The number of points to subsample in a “greedy permutation,” or a furthest point sampling of the points. These points will be used in lieu of the full point cloud for a faster computation, at the expense of some accuracy, which can be bounded as a maximum bottleneck distance to all diagrams on the original point set. - **verbose** (boolean, optional, default True) - Whether to print out information about this object as it is constructed. ### Attributes #### dgm_ After transform, dgm_ contains computed persistence diagrams in each dimension. - **Type:** list of ndarray, each shape (n_pairs, 2) #### cocycles_ A list of representative cocycles in each dimension. The list in each dimension is parallel to the diagram in that dimension; that is, each entry of the list is a representative cocycle of the corresponding point expressed as an ndarray(K, d+1), where K is the number of nonzero values of the cocycle and d is the dimension of the cocycle. The first d columns of each array index into the simplices of the (subsampled) point cloud, and the last column is the value of the cocycle at that simplex. - **Type:** list (size maxdim) of list of ndarray #### dperm2all_ The distance matrix used in the computation if n_perm is none. Otherwise, the distance from all points in the permutation to all points in the dataset. - **Type:** ndarray(n_samples, n_samples) or ndarray (n_perm, n_samples) if n_perm #### metric_ The metric to use when calculating distance between instances in a feature array. If metric is a string, it must be one of the options specified in pairwise_distances, including “euclidean”, “manhattan”, or “cosine”. Alternatively, if metric is a callable function, it is called on each pair of instances (rows) and the resulting value recorded. The callable should take two arrays from X as input and return a value indicating the distance between them. - **Type:** string or callable #### num_edges The number of edges added during the computation. - **Type:** int #### idx_perm Index into the original point cloud of the points used as a subsample in the greedy permutation. - **Type:** ndarray(n_perm) if n_perm > 0 #### r_cover Covering radius of the subsampled points. If n_perm <= 0, then the full point cloud was used and this is 0. - **Type:** float ### Examples ```python from ripser import Rips import tadasets data = tadasets.dsphere(n=110, d=2)[0] rips = Rips() rips.transform(data) rips.plot() ``` ``` -------------------------------- ### Load and Display Image Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Loads an image file and displays its original and grayscale versions. Ensure 'Cells.jpg' is in the same directory. ```python cells_original = plt.imread("Cells.jpg") cells_grey = np.asarray(PIL.Image.fromarray(cells_original).convert("L")) plt.subplot(121) plt.title(cells_original.shape) plt.imshow(cells_original) plt.axis("off") plt.subplot(122) plt.title(cells_grey.shape) plt.imshow(cells_grey, cmap="gray") plt.axis("off") plt.show() ``` -------------------------------- ### Import Libraries for Sparse Distance Matrices Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Sparse Distance Matrices.ipynb Imports necessary libraries including NumPy, Matplotlib, Scikit-learn, SciPy sparse, Ripser, Persim, and Tadasets. ```python import numpy as np import matplotlib.pyplot as plt from sklearn.metrics.pairwise import pairwise_distances from scipy import sparse from ripser import ripser from persim import plot_diagrams import tadasets ``` -------------------------------- ### Plot Full and Sparse Persistence Diagrams Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Compares the persistence diagrams generated from the full filtration and the sparse filtration. This allows for visual assessment of the approximation quality. Requires `plot_diagrams`. ```python # And plot the persistence diagrams on top of each other plt.figure(figsize=(10, 5)) plt.subplot(121) plot_diagrams(resultfull["dgms"], show=False) plt.title("Full Filtration: Elapsed Time %g Seconds" % timefull) plt.subplot(122) plt.title( "Sparse Filtration (%.3g%% Added)\\nElapsed Time %g Seconds" % (percent_added, timesparse) ) plot_diagrams(resultsparse["dgms"], show=False) ``` -------------------------------- ### Visualize Persistence Diagrams for Dense and Sparse Filtrations Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Sparse Distance Matrices.ipynb Plots the original point cloud and the persistence diagrams generated from both the dense and sparse filtrations. This visualization confirms that both methods produce the same topological features. ```python plt.figure(figsize=(12, 4)) plt.subplot(131) plt.scatter(data[:, 0], data[:, 1]) plt.title("Point Cloud") plt.subplot(132) plot_diagrams(results0["dgms"], show=False) plt.title("Dense Filtration") plt.subplot(133) plt.title("Sparse Filtration") plot_diagrams(results1["dgms"], show=False) plt.tight_layout() plt.show() ``` -------------------------------- ### Compare Dense and Sparse Filtration Edge Counts Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Sparse Distance Matrices.ipynb Performs a dense filtration with a specified threshold and a sparse filtration using a pre-computed sparse distance matrix. It then prints the number of edges added in each filtration, demonstrating that they are identical. ```python thresh = 1.5 results0 = ripser(data, thresh=thresh, maxdim=1) D = makeSparseDM(data, thresh) results1 = ripser(D, distance_matrix=True) print("%i edges added in the dense filtration" % results0["num_edges"]) print("%i edges added in the sparse filtration" % results1["num_edges"]) ``` -------------------------------- ### Generate Torus Loop and Compute Homology (1:2 ratio) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Moebius Strip And The Field of Coefficients.ipynb Generates a loop on a torus with a 1:2 ratio of revolutions around the small and large circles, then computes persistent homology using $\mathbb{Z}/2$ and $\mathbb{Z}/3$ coefficients. This configuration is used to demonstrate the effect of coefficient fields on the resulting persistence diagrams, particularly for a Moebius strip boundary. ```python X[:, 0] = (R + r * np.cos(t)) * np.cos(2 * t) X[:, 1] = (R + r * np.cos(t)) * np.sin(2 * t) X[:, 2] = r * np.sin(t) ## Step 2: Compute persistent homology dgms2 = ripser(X, coeff=2ization["dgms"] dgms3 = ripser(X, coeff=3ization["dgms"]) fig = plt.figure(figsize=(9, 3)) ax = fig.add_subplot(131, projection="3d") ax.scatter(X[:, 0], X[:, 1], X[:, 2]) ax.set_aspect("equal") plt.title("Generated Loop") plt.subplot(132) plot_diagrams(dgms2) plt.title("$\mathbb{Z} / 2$") plt.subplot(133) plot_diagrams(dgms3) plt.title("$\mathbb{Z} / 3$") plt.show() ``` -------------------------------- ### Generate and Plot Point Cloud Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Generates a 2D sphere point cloud with noise and displays it using matplotlib. This serves as the dataset for demonstrating subsampling. ```python X = tadasets.dsphere(d=1, n=2000, r=5, noise=1) plt.scatter(X[:, 0], X[:, 1]) plt.axis("equal") plt.show() ``` -------------------------------- ### Generate Gaussian Blob Image Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Constructs a sample image with three negative Gaussian blobs of varying intensities to test the lower star filtration. ```python ts = np.linspace(-1, 1, 100) x1 = np.exp(-(ts**2) / (0.1**2)) ts -= 0.4 x2 = np.exp(-(ts**2) / (0.1**2)) img = ( -x1[None, :] * x1[:, None] - 2 * x1[None, :] * x2[:, None] - 3 * x2[None, :] * x2[:, None] ) plt.imshow(img) plt.show() ``` -------------------------------- ### Analyze Approximation Accuracy Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Calculates and prints the covering radius and the bottleneck distances between the persistence diagrams of the full and subsampled point clouds. This quantifies the accuracy of the approximation. ```python print("Twice Covering radius: %.3g" % (2 * r_cover)) for dim, (I1, I2) in enumerate(zip(dgms_full, dgms_sub)): bdist = bottleneck(I1, I2) print("H%i bottleneck distance: %.3g" % (dim, bdist)) ``` -------------------------------- ### Compute and Plot Persistence Diagrams Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md Compute persistence diagrams from random data using the `ripser` function and visualize them with `plot_diagrams`. Requires numpy and persim. ```python import numpy as np from ripser import ripser from persim import plot_diagrams data = np.random.random((100,2)) diagrams = ripser(data)['dgms'] plot_diagrams(diagrams, show=True) ``` -------------------------------- ### Generate Noisy Circles Dataset Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Sparse Distance Matrices.ipynb Creates a dataset composed of two noisy circles using Tadasets. This data is used to compare dense and sparse filtration methods. ```python data = np.concatenate( [ tadasets.dsphere(n=500, d=1, r=5, noise=0.5), tadasets.dsphere(n=100, d=1, r=1, noise=0.2), ] ) plt.scatter(data[:, 0], data[:, 1]) ``` -------------------------------- ### Import necessary libraries Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Moebius Strip And The Field of Coefficients.ipynb Imports required libraries for numerical operations, plotting, and topological data analysis. ```python import numpy as np import matplotlib.pyplot as plt from ripser import ripser from persim import plot_diagrams ``` -------------------------------- ### Clone robin-hood-hashing for optional performance boost Source: https://github.com/scikit-tda/ripser.py/blob/master/README.md Clone the robin-hood-hashing repository to potentially improve Ripser.py's performance by using a faster hash map implementation. This is an optional step. ```bash # Run this command at the root of the project git clone https://github.com/martinus/robin-hood-hashing robinhood ``` -------------------------------- ### Import Libraries forripser.py Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Imports necessary libraries for the ripser.py module, including ripser, persim, tadasets, numpy, matplotlib, pairwise_distances, sparse, and time. ```python from ripser import ripser from persim import plot_diagrams import tadasets import numpy as np import matplotlib.pyplot as plt from sklearn.metrics.pairwise import pairwise_distances from scipy import sparse import time ``` -------------------------------- ### Perform Lower Star Filtration and Plot Results Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Time Series.ipynb Constructs a sparse distance matrix representing the time series, performs the sublevelset filtration using ripser to compute the persistence diagram (H0), and visualizes both the original time series and its persistence diagram. Edges connect adjacent points, and their weights are determined by the maximum height of the connected points. Vertex birth times are set by the point's height. ```python # Add edges between adjacent points in the time series, with the "distance" # along the edge equal to the max value of the points it connects I = np.arange(N - 1) J = np.arange(1, N) V = np.maximum(x[0:-1], x[1::]) # Add vertex birth times along the diagonal of the distance matrix I = np.concatenate((I, np.arange(N))) J = np.concatenate((J, np.arange(N))) V = np.concatenate((V, x)) # Create the sparse distance matrix D = sparse.coo_matrix((V, (I, J)), shape=(N, N)).tocsr() dgm0 = ripser(D, maxdim=0, distance_matrix=True)("dgms")[0] dgm0 = dgm0[dgm0[:, 1] - dgm0[:, 0] > 1e-3, :] allgrid = np.unique(dgm0.flatten()) allgrid = allgrid[allgrid < np.inf] xs = np.unique(dgm0[:, 0]) ys = np.unique(dgm0[:, 1]) ys = ys[ys < np.inf] # Plot the time series and the persistence diagram plt.figure(figsize=(12, 6)) ylims = [-1, 6.5] plt.subplot(121) plt.plot(t, x) ax = plt.gca() ax.set_yticks(allgrid) ax.set_xticks([]) plt.ylim(ylims) plt.grid(linewidth=1, linestyle="--") plt.title("$\cos(2 \pi t) + t$") plt.xlabel("t") plt.subplot(122) ax = plt.gca() ax.set_yticks(ys) ax.set_xticks(xs) plt.ylim(ylims) plt.grid(linewidth=1, linestyle="--") plot_diagrams(dgm0, size=50) plt.title("Persistence Diagram") plt.show() ``` -------------------------------- ### Import Libraries for Time Series Analysis Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Time Series.ipynb Imports necessary libraries including numpy, matplotlib, scipy.sparse, ripser, and persim for data manipulation, plotting, and topological data analysis. ```python import numpy as np import matplotlib.pyplot as plt from scipy import sparse from ripser import ripser from persim import plot_diagrams ``` -------------------------------- ### Plot Original and Sparse Distance Matrices Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Visualizes the original dense distance matrix and the resulting sparse distance matrix. This helps in understanding the sparsity introduced by the approximation. Requires `matplotlib.pyplot` and `pairwise_distances`. ```python # Plot the sparse distance matrix and edges that were added plt.figure(figsize=(10, 5)) plt.subplot(121) D = pairwise_distances(X, metric="euclidean") plt.imshow(D) plt.title("Original Distance Matrix: %i Edges" % resultfull["num_edges"]) plt.subplot(122) DSparse = DSparse.toarray() DSparse = DSparse + DSparse.T plt.imshow(DSparse) plt.title("Sparse Distance Matrix: %i Edges" % resultsparse["num_edges"]) ``` -------------------------------- ### Generate a noisy circle point cloud Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Creates a 2D point cloud representing a noisy circle with 8 points using NumPy for random number generation and array manipulation. ```python N = 8 np.random.seed(2) t = np.linspace(0, 2 * np.pi, N + 1)[0:N] x = np.array([np.cos(t), np.sin(t)]).T x += np.random.randn(x.shape[0], 2) * 0.1 plt.scatter(x[:, 0], x[:, 1]) plt.axis("equal") plt.show() ``` -------------------------------- ### Compute and Plot Lower Star Filtration Diagram Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Computes the 0-dimensional lower star filtration for the test image and visualizes the resulting persistence diagram alongside the original image. ```python dgm = lower_star_img(img) plt.figure(figsize=(10, 5)) plt.subplot(121) plt.imshow(img) plt.colorbar() plt.title("Test Image") plt.subplot(122) plot_diagrams(dgm) plt.title("0-D Persistence Diagram") plt.tight_layout() plt.show() ``` -------------------------------- ### Generate and Plot Time Series Data Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Time Series.ipynb Sets up a 1D time series using a cosine function with a linear trend and plots it. This serves as the input data for the filtration process. ```python N = 100 # The number of points t = np.linspace(0, 5, N) x = np.cos(2 * np.pi * t) + t plt.plot(t, x) plt.title("$\cos(2 \pi t) + t$") plt.xlabel("t") ``` -------------------------------- ### Greedy Permutation (Furthest Points Sampling) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Implements a naive O(N^2) algorithm for furthest points sampling to determine insertion radii for points in a distance matrix. ```python def getGreedyPerm(D): """ A Naive O(N^2) algorithm to do furthest points sampling Parameters ---------- D : ndarray (N, N) An NxN distance matrix for points Return ------ lamdas: list Insertion radii of all points """ N = D.shape[0] # By default, takes the first point in the permutation to be the # first point in the point cloud, but could be random perm = np.zeros(N, dtype=np.int64) lambdas = np.zeros(N) ds = D[0, :] for i in range(1, N): idx = np.argmax(ds) perm[i] = idx lambdas[i] = ds[idx] ds = np.minimum(ds, D[idx, :]) return lambdas[perm] ``` -------------------------------- ### Compute Persistent Homology on Subsampled Point Cloud Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Performs persistent homology on a subsampled point cloud (400 points) and measures the computation time. This demonstrates the speedup achieved by subsampling. ```python tic = time.time() res = ripser(X, n_perm=400) toc = time.time() print("Elapsed Time Subsampled Point Cloud: %.3g seconds" % (toc - tic)) dgms_sub = res["dgms"] idx_perm = res["idx_perm"] r_cover = res["r_cover"] ``` -------------------------------- ### Plot persistence diagram and highlight max persistence point Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Plots the persistence diagrams generated by Ripser and highlights the point with the maximum persistence in the 1D diagram using a black 'x' marker. ```python dgm1 = diagrams[1] idx = np.argmax(dgm1[:, 1] - dgm1[:, 0]) plot_diagrams(diagrams, show=False) plt.scatter(dgm1[idx, 0], dgm1[idx, 1], 20, "k", "x") plt.title("Max 1D birth = %.3g, death = %.3g" % (dgm1[idx, 0], dgm1[idx, 1])) plt.show() ``` -------------------------------- ### Specify Maximum Radius (Threshold=1) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Demonstrates the effect of setting a `thresh` value of 1 on the persistent homology diagrams. Classes with birth times below this threshold may not appear. ```python dgms = ripser(data, thresh=1) plot_diagrams(dgms, show=True) ``` -------------------------------- ### Import Libraries for Image Filtration Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Imports necessary libraries including numpy, matplotlib, scipy, PIL, persim, and ripser for image processing and topological data analysis. ```python import numpy as np import matplotlib.pyplot as plt from scipy import ndimage import PIL from persim import plot_diagrams from ripser import lower_star_img ``` -------------------------------- ### Compute and Plot Lower Star Filtration Diagram Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Computes the lower star filtration of the negative grayscale image and plots the persistence diagram with lifetimes. This is used to find local maxima. ```python dgm = lower_star_img(-cells_grey) plt.figure(figsize=(6, 6)) plot_diagrams(dgm, lifetime=True) plt.show() ``` -------------------------------- ### Compute Persistent Homology on Full Point Cloud Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Greedy Subsampling for Fast Approximate Computation.ipynb Calculates the persistent homology (H0 and H1) for the entire 2000-point dataset and measures the computation time. ```python tic = time.time() dgms_full = ripser(X)("dgms") toc = time.time() print("Elapsed Time Full Point Cloud: %.3g seconds" % (toc - tic)) ``` -------------------------------- ### Plot 1-Form Cocycle at a Specific Threshold Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Visualizes a 1-form cocycle at a given threshold. This is useful for understanding the structure of the cocycle at a particular filtration value. ```python plotCocycle2D(D, x, cocycle, thresh1) plt.title("1-Form Thresh=%g" % thresh1) plt.show() ``` -------------------------------- ### Load Autoreload Extension Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Loads the autoreload extension for interactive development, ensuring changes in imported modules are automatically reloaded. ```python %load_ext autoreload %autoreload 2 ``` -------------------------------- ### Plotting a 2D cocycle Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Visualizes a cocycle on a 2D point cloud by drawing edges below a given threshold and labeling them with cocycle values. Vertex labels are shown in red, and edge orientations are indicated by shades of gray. ```python def plotCocycle2D(D, X, cocycle, thresh): """ Given a 2D point cloud X, display a cocycle projected onto edges under a given threshold "thresh" """ # Plot all edges under the threshold N = X.shape[0] t = np.linspace(0, 1, 10) c = plt.get_cmap("Greys") C = c(np.array(np.round(np.linspace(0, 255, len(t))), dtype=np.int32)) C = C[:, 0:3] edges_drawn = 0 for i in range(N): for j in range(i + 1, N): if D[i, j] <= thresh: Y = np.zeros((len(t), 2)) Y[:, 0] = X[i, 0] + t * (X[j, 0] - X[i, 0]) Y[:, 1] = X[i, 1] + t * (X[j, 1] - X[i, 1]) drawLineColored(Y, C) edges_drawn += 1 # Plot cocycle projected to edges under the chosen threshold for k in range(cocycle.shape[0]): [i, j, val] = cocycle[k, :] if D[i, j] <= thresh: [i, j] = [min(i, j), max(i, j)] a = 0.5 * (X[i, :] + X[j, :]) plt.text(a[0], a[1], "%g" % val, color="b") # Plot vertex labels for i in range(N): plt.text(X[i, 0], X[i, 1], "%i" % i, color="r") plt.axis("equal") return edges_drawn ``` -------------------------------- ### Compute and Plot Smoothed Image Filtration Diagram Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Computes the lower star filtration of the negative smoothed image and plots the persistence diagram with lifetimes. This is used after applying smoothing and noise. ```python dgm = lower_star_img(-smoothed) plot_diagrams(dgm, lifetime=True) plt.show() ``` -------------------------------- ### Plot 1-Form Cocycle Near Birth Time Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Visualizes a 1-form cocycle by projecting it onto edges with lengths less than or equal to the birth time. This helps verify the cocycle condition at the lower bound of its persistence interval. ```python thresh = ( dgm1[idx, 0] + 1e-5 ) # Project cocycle onto edges that have lengths less than or equal to the birth time e = plotCocycle2D(D, x, cocycle, thresh) plt.title("1-Form Thresh=%g, %i Edges Drawn" % (thresh, e)) plt.show() ``` -------------------------------- ### Run Ripser with cocycle computation Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Computes persistent cohomology for the point cloud `x` using Ripser. It enables cocycle storage and specifies the coefficient field as Z_17. ```python result = ripser(x, coeff=17, do_cocycles=True) print(result.keys()) diagrams = result["dgms"] cocycles = result["cocycles"] D = result["dperm2all"] ``` -------------------------------- ### Adjusting Threshold to Find a Valid Cocycle Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb This code snippet demonstrates how to find a threshold slightly below a given threshold to ensure the cocycle condition is met. It plots the cocycle at both the original and adjusted thresholds for comparison. ```python edges_sorted = np.sort(D.flatten()) thresh2 = edges_sorted[np.argmin(np.abs(edges_sorted - thresh1)) - 1] plt.figure(figsize=(12, 6)) plt.subplot(121) e1 = plotCocycle2D(D, x, cocycle, thresh1) plt.title("1-Form Thresh=%g, %i Edges Drawn" % (thresh1, e1)) plt.subplot(122) e2 = plotCocycle2D(D, x, cocycle, thresh2) plt.title("1-Form Thresh=%g, %i Edges Drawn" % (thresh2, e2)) plt.show() ``` -------------------------------- ### Approximate Sparse Distance Matrix Calculation Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Generates a sparse distance matrix with re-weighted edges, providing a (1+epsilon) multiplicative approximation of the true persistence diagrams. It involves neighborhood search, pruning, and warping edge lengths based on insertion radii and the approximation factor. ```python def getApproxSparseDM(lambdas, eps, D): """ Purpose: To return the sparse edge list with the warped distances, sorted by weight Parameters ---------- lambdas: list insertion radii for points eps: float epsilon approximation constant D: ndarray NxN distance matrix, okay to modify because last time it's used Return ------ DSparse: scipy.sparse A sparse NxN matrix with the reweighted edges """ N = D.shape[0] E0 = (1 + eps) / eps E1 = (1 + eps) ** 2 / eps # Create initial sparse list candidates (Lemma 6) # Search neighborhoods nBounds = ((eps**2 + 3 * eps + 2) / eps) * lambdas # Set all distances outside of search neighborhood to infinity D[D > nBounds[:, None]] = np.inf [II, JJ] = np.meshgrid(np.arange(N), np.arange(N)) idx = II < JJ II = II[(D < np.inf) * (idx == 1)] JJ = JJ[(D < np.inf) * (idx == 1)] D = D[(D < np.inf) * (idx == 1)] # Prune sparse list and update warped edge lengths (Algorithm 3 pg. 14) minlam = np.minimum(lambdas[II], lambdas[JJ]) maxlam = np.maximum(lambdas[II], lambdas[JJ]) # Rule out edges between vertices whose balls stop growing before they touch # or where one of them would have been deleted. M stores which of these # happens first M = np.minimum((E0 + E1) * minlam, E0 * (minlam + maxlam)) t = np.arange(len(II)) t = t[D <= M] (II, JJ, D) = (II[t], JJ[t], D[t]) minlam = minlam[t] maxlam = maxlam[t] # Now figure out the metric of the edges that are actually added t = np.ones(len(II)) # If cones haven't turned into cylinders, metric is unchanged t[D <= 2 * minlam * E0] = 0 # Otherwise, if they meet before the M condition above, the metric is warped D[t == 1] = 2.0 * (D[t == 1] - minlam[t == 1] * E0) # Multiply by 2 convention return sparse.coo_matrix((D, (II, JJ)), shape=(N, N)).tocsr() ``` -------------------------------- ### Extract and print cocycle values Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb Extracts the representative cocycle for the 1D cohomology class with maximum persistence and prints its values. It also sets a threshold for plotting edges based on the death time of this class. ```python cocycle = cocycles[1][idx] print(cocycle) thresh1 = ( dgm1[idx, 1] + 0.01 ) # Project cocycle onto edges less than or equal to death time ``` -------------------------------- ### Create Sparse Distance Matrix from Point Cloud Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Sparse Distance Matrices.ipynb Generates a sparse distance matrix from a point cloud, including only edges with lengths below a specified threshold. This function is useful for reducing computation in large datasets. ```python def makeSparseDM(X, thresh): N = X.shape[0] D = pairwise_distances(X, metric="euclidean") [I, J] = np.meshgrid(np.arange(N), np.arange(N)) I = I[D <= thresh] J = J[D <= thresh] V = D[D <= thresh] return sparse.coo_matrix((V, (I, J)), shape=(N, N)).tocsr() ``` -------------------------------- ### Compute Homology over Z/3Z Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Computes the persistent homology for the H1 component over the prime field Z/3Z by specifying `coeff=3`. This demonstrates homology computation with a prime modulus. ```python # Homology over Z/3Z dgms = ripser(data, coeff=3)['dgms'] plot_diagrams(dgms, plot_only=[1], title="Homology of Z/3Z", show=True) ``` -------------------------------- ### Specify Maximum Radius (Threshold=999) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Shows the persistent homology diagrams when a very large `thresh` value (999) is used. This effectively includes all possible simplexes within the filtration. ```python dgms = ripser(data, thresh=999) plot_diagrams(dgms, show=True) ``` -------------------------------- ### Compute and Plot Default Diagrams Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Computes the persistent homology diagrams (H0 and H1) for the provided data using default arguments and displays them. This is the most straightforward way to use Ripser. ```python dgms = ripser(data)['dgms'] plot_diagrams(dgms, show=True) ``` -------------------------------- ### Identify and Highlight Pixel Representatives Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Identifies 0-dimensional homology classes with a lifetime above a specified threshold and highlights their corresponding pixel representatives on the original image. ```python thresh = 70 idxs = np.arange(dgm.shape[0]) idxs = idxs[np.abs(dgm[:, 1] - dgm[:, 0]) > thresh] plt.figure(figsize=(8, 5)) plt.imshow(cells_original) X, Y = np.meshgrid(np.arange(smoothed.shape[1]), np.arange(smoothed.shape[0])) X = X.flatten() Y = Y.flatten() for idx in idxs: bidx = np.argmin(np.abs(smoothed + dgm[idx, 0])) plt.scatter(X[bidx], Y[bidx], 20, "k") plt.axis("off") plt.show() ``` -------------------------------- ### Specify Maximum Radius (Threshold=2) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Illustrates the impact of a `thresh` value of 2 on the computed persistent homology diagrams. Higher thresholds can lead to fewer observed homology features. ```python dgms = ripser(data, thresh=2) plot_diagrams(dgms, show=True) ``` -------------------------------- ### Apply Colormap to Diagram Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Applies a specified colormap ('seaborn' in this case) to the persistent homology diagram. This can enhance the visual representation of the data. ```python plot_diagrams(dgms, colormap="seaborn") ``` -------------------------------- ### Plot Generator Lifetimes Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Visualizes the lifetime of homology generators by setting `lifetime=True`. This option highlights the duration for which each homology class persists. ```python plot_diagrams(dgms, lifetime=True) ``` -------------------------------- ### Apply Smoothing and Noise to Image Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Lower Star Image Filtrations.ipynb Applies a uniform filter for local averaging and adds a small amount of Gaussian noise to the image. This helps in finding unique pixel representatives for homology classes. ```python smoothed = ndimage.uniform_filter(cells_grey.astype(np.float64), size=10) smoothed += 0.01 * np.random.randn(*smoothed.shape) plt.figure(figsize=(10, 5)) plt.subplot(121) im = plt.imshow(cells_grey, cmap="gray") plt.colorbar(im, fraction=0.03) plt.subplot(122) im = plt.imshow(smoothed, cmap="gray") plt.colorbar(im, fraction=0.03) plt.tight_layout() plt.show() ``` -------------------------------- ### Compute Homology over Z/7Z Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Computes the persistent homology for the H1 component over the prime field Z/7Z by specifying `coeff=7`. Note: The provided code snippet incorrectly uses `coeff=3` for Z/7Z. The correct usage would be `coeff=7`. ```python # Homology over Z/7Z dgms = ripser(data, coeff=3)['dgms'] plot_diagrams(dgms, plot_only=[1], title="Homology of Z/7Z", show=True) # Only plot H_1 ``` -------------------------------- ### Helper function to draw colored lines Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Representative Cocycles.ipynb A utility function to draw lines with specified colors, used for visualizing edges in the cocycle plot. ```python def drawLineColored(X, C): for i in range(X.shape[0] - 1): plt.plot(X[i : i + 2, 0], X[i : i + 2, 1], c=C[i, :], linewidth=3) ``` -------------------------------- ### Compute Sparse Filtration Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Computes a sparse filtration using approximate sparse distance matrix. This is useful for large datasets where computing the full distance matrix is infeasible. Requires `ripser`, `getApproxSparseDM`, `getGreedyPerm`, and `pairwise_distances`. ```python eps = 0.4 # Compute the sparse filtration tic = time.time() # First compute all pairwise distances and do furthest point sampling D = pairwise_distances(X, metric="euclidean") lambdas = getGreedyPerm(D) # Now compute the sparse distance matrix DSparse = getApproxSparseDM(lambdas, eps, D) # Finally, compute the filtration resultsparse = ripser(DSparse, distance_matrix=True) toc = time.time() timesparse = toc - tic percent_added = 100.0 * float(resultsparse["num_edges"]) / resultfull["num_edges"] print( "Elapsed Time: %.3g seconds, %i Edges added" % (timesparse, resultsparse["num_edges"]) ) ``` -------------------------------- ### Compute Approximate Sparse Filtration Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Approximate Sparse Filtrations.ipynb Calculates the approximate sparse filtration by first computing pairwise distances, then performing furthest point sampling to obtain insertion radii, and finally computing the sparse distance matrix. ```python eps = 0.1 # Compute the sparse filtration tic = time.time() # First compute all pairwise distances and do furthest point sampling D = pairwise_distances(X, metric="euclidean") lambdas = getGreedyPerm(D) ``` -------------------------------- ### Specify Maximum Radius (Threshold) Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Restricts the maximum radius of the Vietoris-Rips complex by setting the `thresh` argument. This can affect the birth and death times of homology classes. ```python dgms = ripser(data, thresh=0.2) plot_diagrams(dgms, show=True) ``` -------------------------------- ### Ripser.py Citation Bibtex Entry Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md Use this bibtex entry when citing the Ripser.py package in academic work. It includes details such as DOI, URL, publication year, and author information. ```default @article{ctralie2018ripser, doi = {10.21105/joss.00925}, url = {https://doi.org/10.21105/joss.00925}, year = {2018}, month = {Sep}, publisher = {The Open Journal}, volume = {3}, number = {29}, pages = {925}, author = {Christopher Tralie and Nathaniel Saul and Rann Bar-On}, title = {{Ripser.py}: A Lean Persistent Homology Library for Python}, journal = {The Journal of Open Source Software} } ``` -------------------------------- ### Specify Maximum Homology Dimension Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/notebooks/Basic Usage.ipynb Computes persistent homology up to dimension 2 (H0, H1, and H2) by setting `maxdim=2`. Be aware that higher dimensions can be computationally intensive. ```python dgms = ripser(data, maxdim=2)['dgms'] plot_diagrams(dgms, show=True) ``` -------------------------------- ### Scikit-learn Style Persistent Homology Source: https://github.com/scikit-tda/ripser.py/blob/master/docs/index.md Use the `Rips` class as a Scikit-learn transformer to compute and plot persistence diagrams. This provides an alternative interface for integration with Scikit-learn pipelines. ```python import numpy as np from ripser import Rips rips = Rips() data = np.random.random((100,2)) diagrams = rips.fit_transform(data) rips.plot(diagrams) ```