Source code for gtda.plotting.diagram_representations

"""Plotting functions for (vector) representations of persistence diagrams."""
# License: GNU AGPLv3

import numpy as np
import plotly.graph_objs as gobj


[docs]def plot_betti_curves(betti_numbers, samplings, homology_dimensions=None, plotly_params=None): """Plot Betti curves by homology dimension. Parameters ---------- betti_numbers : ndarray of shape (n_homology_dimensions, n_bins) Betti numbers, i.e. the y-coordinates of Betti curves. Entry i along axis 0 is assumed to contain the Betti numbers for a discretised Betti curve in homology dimension i. samplings : ndarray of shape (n_homology_dimensions, n_bins) Filtration parameter values to be used as the x-coordinates of the Betti curves. homology_dimensions : list, tuple or None, optional, default: ``None`` Which homology dimensions to include in the plot. If ``None``, all available homology dimensions will be used. plotly_params : dict or None, optional, default: ``None`` Custom parameters to configure the plotly figure. Allowed keys are ``"traces"`` and ``"layout"``, and the corresponding values should be dictionaries containing keyword arguments as would be fed to the :meth:`update_traces` and :meth:`update_layout` methods of :class:`plotly.graph_objects.Figure`. Returns ------- fig : :class:`plotly.graph_objects.Figure` object Figure representing the Betti curves. """ if homology_dimensions is None: _homology_dimensions = list(range(betti_numbers.shape[0])) else: _homology_dimensions = homology_dimensions layout = { "xaxis1": { "title": "Filtration parameter", "side": "bottom", "type": "linear", "ticks": "outside", "anchor": "x1", "showline": True, "zeroline": True, "showexponent": "all", "exponentformat": "e" }, "yaxis1": { "title": "Betti number", "side": "left", "type": "linear", "ticks": "outside", "anchor": "y1", "showline": True, "zeroline": True, "showexponent": "all", "exponentformat": "e" }, "plot_bgcolor": "white" } fig = gobj.Figure(layout=layout) fig.update_xaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False) fig.update_yaxes(zeroline=True, linewidth=1, linecolor="black", mirror=False) for dim in _homology_dimensions: fig.add_trace(gobj.Scatter(x=samplings[dim], y=betti_numbers[dim], mode="lines", showlegend=True, hoverinfo="none", name=f"H{int(dim)}")) # Update traces and layout according to user input if plotly_params: fig.update_traces(plotly_params.get("traces", None)) fig.update_layout(plotly_params.get("layout", None)) return fig
[docs]def plot_betti_surfaces(betti_curves, samplings=None, homology_dimensions=None, plotly_params=None): """Plot Betti surfaces (Betti numbers against "time" and filtration parameter) by homology dimension. Parameters ---------- betti_curves : ndarray of shape (n_samples, n_homology_dimensions, \ n_bins) Collection whose each entry contains the Betti numbers for ``n_homology_dimensions`` discretised Betti curves. Index i along axis 1 is assumed to correspond to homology dimension i. samplings : ndarray of shape (n_homology_dimensions, n_bins) Filtration parameter values to be used as one of the independent variables when plotting the Betti surfaces. The other independent variable is "time", i.e. the sample index. homology_dimensions : list, tuple or None, optional, default: ``None`` Homology dimensions for which the Betti surfaces should be plotted. If ``None``, all available dimensions will be used. samplings : ndarray of shape (n_homology_dimensions, n_bins) For each homology dimension, (filtration parameter) values to be used on the x-axis against the corresponding values in `betti_curves` on the y-axis. plotly_params : dict or None, optional, default: ``None`` Custom parameters to configure the plotly figure. Allowed keys are ``"traces"`` and ``"layout"``, and the corresponding values should be dictionaries containing keyword arguments as would be fed to the :meth:`update_traces` and :meth:`update_layout` methods of :class:`plotly.graph_objects.Figure`. Returns ------- figs/fig : tuple of :class:`plotly.graph_objects.Figure`/\ :class:`plotly.graph_objects.Figure` object If ``n_samples > 1``, a tuple of figures representing the Betti surfaces, with one figure per dimension in `homology_dimensions`. Otherwise, a single figure representing the Betti curve of the single sample present. """ if homology_dimensions is None: _homology_dimensions = list(range(betti_curves.shape[1])) else: _homology_dimensions = homology_dimensions scene = { "xaxis": { "title": "Filtration parameter", "type": "linear", "showexponent": "all", "exponentformat": "e" }, "yaxis": { "title": "Time", "type": "linear", "showexponent": "all", "exponentformat": "e" }, "zaxis": { "title": "Betti number", "type": "linear", "showexponent": "all", "exponentformat": "e" } } if betti_curves.shape[0] == 1: return plot_betti_curves( betti_curves[0], samplings, homology_dimensions=homology_dimensions, plotly_params=plotly_params ) else: figs = [] for dim in _homology_dimensions: fig = gobj.Figure() fig.update_layout(scene=scene, title=f"Betti surface for homology " f"dimension {int(dim)}") fig.add_trace(gobj.Surface(x=samplings[dim], y=np.arange(betti_curves.shape[0]), z=betti_curves[:, dim], connectgaps=True, hoverinfo="none")) # Update traces and layout according to user input if plotly_params: fig.update_traces(plotly_params.get("traces", None)) fig.update_layout(plotly_params.get("layout", None)) figs.append(fig) return tuple(figs)