(
    X,
    maxdim=1,
    thresh=np.inf,
    coeff=2,
    distance_matrix=False,
    do_cocycles=False,
    metric="euclidean",
    n_perm=None,
)
return ret
Compute persistence diagrams for X.

    X can be a data set of points or a distance matrix. When using a data set
    as X it will be converted to a distance matrix using the metric specified.

    Parameters
    ----------

    X : ndarray (n_samples, n_features)
        A numpy array of either data or distance matrix (also pass `distance_matrix=True`). Can also be a sparse distance matrix of type scipy.sparse

    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, default infinity
        Maximum distances considered when constructing filtration.  If infinity, compute the entire filtration.

    coeff: int prime, default 2
        Compute homology with coefficients in the prime field Z/pZ for p=coeff.

    distance_matrix: bool, optional, default False
        When True the input matrix X will be considered a distance matrix.

    do_cocycles: bool, optional, default False
        Computed cocycles will be available in the `cocycles` value
        of the return dictionary.

    metric: string or callable, optional, default "euclidean"
        Use this metric to compute distances between rows of X.

        "euclidean", "manhattan" and "cosine" are already provided metrics
        to choose from by using their name.

        You can provide a callable function and it will be used with two
        rows as arguments, it will be called once for each pair of rows in X.

        The computed distance will be available in the result dictionary under
        the key `dperm2all`.
    
    n_perm: int, optional, default None
        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

    Returns
    -------
    dict
        The result of the computation.

        .. note::
            Each list in `dgms` has a relative list in `cocycles`.

            >>> r = ripser(...)

            For each dimension ``d`` and index ``k`` then ``r['dgms'][d][k]``
            is the barcode associated to the representative cocycle
            ``r['cocycles'][d][k]``.

        The keys available in the dictionary are the:

            * ``dgms``: list (size maxdim) of ndarray (n_pairs, 2)
                For each dimension less than ``maxdim`` a list of persistence diagrams.
                Each persistent diagram is a pair (birth time, death time).
            * ``cocycles``: list (size maxdim) of list of ndarray
                For each dimension less than ``maxdim`` a list of representative cocycles.
                Each representative cocycle in dimension ``d`` is represented as a
                ndarray of ``(k,d+1)`` elements. Each non zero value of the cocycle
                is laid out in a row, first the ``d`` indices of the simplex and then
                the value of the cocycle on the simplex.  The indices of the simplex
                reference the original point cloud, even if a greedy permutation was used.
            * ``num_edges``: int
                The number of edges added during the computation
            * ``dperm2all``: ndarray(n_samples, n_samples) or ndarray (n_perm, n_samples) if n_perm
                The distance matrix used during the computation. When ``n_perm``
                is not None the distance matrix will only refers to the subsampled
                dataset.
            * ``idx_perm``: ndarray(n_perm) if ``n_perm`` > 0
                Index into the original point cloud of the points used
                as a subsample in the greedy permutation

                    >>> r = ripser(X, n_perm=k)
                    >>> subsampling = X[r['idx_perm']]

            * 'r_cover': float
                Covering radius of the subsampled points.
                If ``n_perm <= 0``, then the full point cloud was used and this is 0

    Examples
    --------

    .. code:: 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)

    Raises
    ------

    ValueError
        If the distance matrix is not square.

    ValueError
        When using both a greedy permutation and a sparse distance matrix.

    ValueError
        When `n_perm` value is bigger than the number of rows in the matrix.

    ValueError
        When `n_perm` is non positive.

    Warns
    ----

        When using a square matrix without toggling `distance_matrix` to True.

        When there are more columns than rows (as each row is a different data point).
Compute persistence diagrams for X.
Compute persistence diagrams for X .
def ripser(
    X,
    maxdim=1,
    thresh=np.inf,
    coeff=2,
    distance_matrix=False,
    do_cocycles=False,
    metric="euclidean",
    n_perm=None,
):
    """Compute persistence diagrams for X.

    X can be a data set of points or a distance matrix. When using a data set
    as X it will be converted to a distance matrix using the metric specified.

    Parameters
    ----------

    X : ndarray (n_samples, n_features)
        A numpy array of either data or distance matrix (also pass `distance_matrix=True`). Can also be a sparse distance matrix of type scipy.sparse

    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, default infinity
        Maximum distances considered when constructing filtration.  If infinity, compute the entire filtration.

    coeff: int prime, default 2
        Compute homology with coefficients in the prime field Z/pZ for p=coeff.

    distance_matrix: bool, optional, default False
        When True the input matrix X will be considered a distance matrix.

    do_cocycles: bool, optional, default False
        Computed cocycles will be available in the `cocycles` value
        of the return dictionary.

    metric: string or callable, optional, default "euclidean"
        Use this metric to compute distances between rows of X.

        "euclidean", "manhattan" and "cosine" are already provided metrics
        to choose from by using their name.

        You can provide a callable function and it will be used with two
        rows as arguments, it will be called once for each pair of rows in X.

        The computed distance will be available in the result dictionary under
        the key `dperm2all`.
    
    n_perm: int, optional, default None
        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

    Returns
    -------
    dict
        The result of the computation.

        .. note::
            Each list in `dgms` has a relative list in `cocycles`.

            >>> r = ripser(...)

            For each dimension ``d`` and index ``k`` then ``r['dgms'][d][k]``
            is the barcode associated to the representative cocycle
            ``r['cocycles'][d][k]``.

        The keys available in the dictionary are the:

            * ``dgms``: list (size maxdim) of ndarray (n_pairs, 2)
                For each dimension less than ``maxdim`` a list of persistence diagrams.
                Each persistent diagram is a pair (birth time, death time).
            * ``cocycles``: list (size maxdim) of list of ndarray
                For each dimension less than ``maxdim`` a list of representative cocycles.
                Each representative cocycle in dimension ``d`` is represented as a
                ndarray of ``(k,d+1)`` elements. Each non zero value of the cocycle
                is laid out in a row, first the ``d`` indices of the simplex and then
                the value of the cocycle on the simplex.  The indices of the simplex
                reference the original point cloud, even if a greedy permutation was used.
            * ``num_edges``: int
                The number of edges added during the computation
            * ``dperm2all``: ndarray(n_samples, n_samples) or ndarray (n_perm, n_samples) if n_perm
                The distance matrix used during the computation. When ``n_perm``
                is not None the distance matrix will only refers to the subsampled
                dataset.
            * ``idx_perm``: ndarray(n_perm) if ``n_perm`` > 0
                Index into the original point cloud of the points used
                as a subsample in the greedy permutation

                    >>> r = ripser(X, n_perm=k)
                    >>> subsampling = X[r['idx_perm']]

            * 'r_cover': float
                Covering radius of the subsampled points.
                If ``n_perm <= 0``, then the full point cloud was used and this is 0

    Examples
    --------

    .. code:: 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)

    Raises
    ------

    ValueError
        If the distance matrix is not square.

    ValueError
        When using both a greedy permutation and a sparse distance matrix.

    ValueError
        When `n_perm` value is bigger than the number of rows in the matrix.

    ValueError
        When `n_perm` is non positive.

    Warns
    ----

        When using a square matrix without toggling `distance_matrix` to True.

        When there are more columns than rows (as each row is a different data point).

    """

    if distance_matrix:
        if not (X.shape[0] == X.shape[1]):
            raise ValueError("Distance matrix is not square")
    else:
        if X.shape[0] == X.shape[1]:
            warnings.warn(
                "The input matrix is square, but the distance_matrix "
                + "flag is off.  Did you mean to indicate that "
                + "this was a distance matrix?"
            )
        elif X.shape[0] < X.shape[1]:
            warnings.warn(
                "The input point cloud has more columns than rows; "
                + "did you mean to transpose?"
            )

    if n_perm and distance_matrix and sparse.issparse(X):
        raise ValueError(
            "Greedy permutation is not supported for sparse distance matrices"
        )
    if n_perm and n_perm > X.shape[0]:
        raise ValueError(
            "Number of points in greedy permutation is greater"
            + " than number of points in the point cloud"
        )
    if n_perm and n_perm < 0:
        raise ValueError(
            "Should be a strictly positive number of points in the greedy permutation"
        )

    idx_perm = np.arange(X.shape[0])
    r_cover = 0.0
    doing_permutation = False
    if n_perm and n_perm < X.shape[0]:
        doing_permutation = True
        idx_perm, lambdas, dperm2all = get_greedy_perm(
            X, n_perm=n_perm, distance_matrix=distance_matrix, metric=metric
        )
        r_cover = lambdas[-1]
        dm = dperm2all[:, idx_perm]
    else:
        if distance_matrix:
            dm = X
        else:
            dm = pairwise_distances(X, metric=metric)
        dperm2all = dm

    n_points = dm.shape[0]
    if not sparse.issparse(dm) and np.sum(np.abs(dm.diagonal()) > 0) > 0:
        # If any of the diagonal elements are nonzero,
        # convert to sparse format, because currently
        # that's the only format that handles nonzero
        # births
        dm = sparse.coo_matrix(dm)

    if sparse.issparse(dm):
        if sparse.isspmatrix_coo(dm):
            # If the matrix is already COO, we need to order the row and column indices
            # lexicographically to avoid errors. See issue #103
            row, col, data = dm.row, dm.col, dm.data
            lex_sort_idx = np.lexsort((col, row))
            row, col, data = row[lex_sort_idx], col[lex_sort_idx], data[lex_sort_idx]
        else:
            # Lexicographic ordering is performed by scipy upon conversion to COO
            coo = dm.tocoo()
            row, col, data = coo.row, coo.col, coo.data
        res = DRFDMSparse(
            row.astype(dtype=np.int32, order="C"),
            col.astype(dtype=np.int32, order="C"),
            np.array(data, dtype=np.float32, order="C"),
            n_points,
            maxdim,
            thresh,
            coeff,
            do_cocycles
        )
    else:
        I, J = np.meshgrid(np.arange(n_points), np.arange(n_points))
        DParam = np.array(dm[I > J], dtype=np.float32)
        res = DRFDM(DParam, maxdim, thresh, coeff, do_cocycles)

    # Unwrap persistence diagrams
    dgms = res["births_and_deaths_by_dim"]
    for dim in range(len(dgms)):
        N = int(len(dgms[dim]) / 2)
        dgms[dim] = np.reshape(np.array(dgms[dim]), [N, 2])

    # Unwrap cocycles
    cocycles = []
    for dim in range(len(res["cocycles_by_dim"])):
        cocycles.append([])
        for j in range(len(res["cocycles_by_dim"][dim])):
            ccl = res["cocycles_by_dim"][dim][j]
            n = int(len(ccl) / (dim + 2))
            ccl = np.reshape(np.array(ccl, dtype=np.int64), [n, dim + 2])
            ccl[:, -1] = np.mod(ccl[:, -1], coeff)
            if doing_permutation:
                # Retain original indices in the point cloud
                ccl[:, 0:-1] = idx_perm[ccl[:, 0:-1]]
            cocycles[dim].append(ccl)

    ret = {
        "dgms": dgms,
        "cocycles": cocycles,
        "num_edges": res["num_edges"],
        "dperm2all": dperm2all,
        "idx_perm": idx_perm,
        "r_cover": r_cover,
    }
    return ret
def ripser ( X , maxdim = 1 , thresh = np . inf , coeff = 2 , distance_matrix = False , do_cocycles = False , metric = "euclidean" , n_perm = None , ) : if distance_matrix : if not ( X . shape [ 0 ] == X . shape [ 1 ] ) : raise ValueError ( "Distance matrix is not square" ) else : if X . shape [ 0 ] == X . shape [ 1 ] : warnings . warn ( "The input matrix is square, but the distance_matrix " + "flag is off.  Did you mean to indicate that " + "this was a distance matrix?" ) elif X . shape [ 0 ] < X . shape [ 1 ] : warnings . warn ( "The input point cloud has more columns than rows; " + "did you mean to transpose?" ) if n_perm and distance_matrix and sparse . issparse ( X ) : raise ValueError ( "Greedy permutation is not supported for sparse distance matrices" ) if n_perm and n_perm > X . shape [ 0 ] : raise ValueError ( "Number of points in greedy permutation is greater" + " than number of points in the point cloud" ) if n_perm and n_perm < 0 : raise ValueError ( "Should be a strictly positive number of points in the greedy permutation" ) idx_perm = np . arange ( X . shape [ 0 ] ) r_cover = 0.0 doing_permutation = False if n_perm and n_perm < X . shape [ 0 ] : doing_permutation = True idx_perm , lambdas , dperm2all = get_greedy_perm ( X , n_perm = n_perm , distance_matrix = distance_matrix , metric = metric ) r_cover = lambdas [ - 1 ] dm = dperm2all [ : , idx_perm ] else : if distance_matrix : dm = X else : dm = pairwise_distances ( X , metric = metric ) dperm2all = dm n_points = dm . shape [ 0 ] if not sparse . issparse ( dm ) and np . sum ( np . abs ( dm . diagonal ( ) ) > 0 ) > 0 : # If any of the diagonal elements are nonzero, # convert to sparse format, because currently # that's the only format that handles nonzero # births dm = sparse . coo_matrix ( dm ) if sparse . issparse ( dm ) : if sparse . isspmatrix_coo ( dm ) : # If the matrix is already COO, we need to order the row and column indices # lexicographically to avoid errors. See issue #103 row , col , data = dm . row , dm . col , dm . data lex_sort_idx = np . lexsort ( ( col , row ) ) row , col , data = row [ lex_sort_idx ] , col [ lex_sort_idx ] , data [ lex_sort_idx ] else : # Lexicographic ordering is performed by scipy upon conversion to COO coo = dm . tocoo ( ) row , col , data = coo . row , coo . col , coo . data res = DRFDMSparse ( row . astype ( dtype = np . int32 , order = "C" ) , col . astype ( dtype = np . int32 , order = "C" ) , np . array ( data , dtype = np . float32 , order = "C" ) , n_points , maxdim , thresh , coeff , do_cocycles ) else : I , J = np . meshgrid ( np . arange ( n_points ) , np . arange ( n_points ) ) DParam = np . array ( dm [ I > J ] , dtype = np . float32 ) res = DRFDM ( DParam , maxdim , thresh , coeff , do_cocycles ) # Unwrap persistence diagrams dgms = res [ "births_and_deaths_by_dim" ] for dim in range ( len ( dgms ) ) : N = int ( len ( dgms [ dim ] ) / 2 ) dgms [ dim ] = np . reshape ( np . array ( dgms [ dim ] ) , [ N , 2 ] ) # Unwrap cocycles cocycles = [ ] for dim in range ( len ( res [ "cocycles_by_dim" ] ) ) : cocycles . append ( [ ] ) for j in range ( len ( res [ "cocycles_by_dim" ] [ dim ] ) ) : ccl = res [ "cocycles_by_dim" ] [ dim ] [ j ] n = int ( len ( ccl ) / ( dim + 2 ) ) ccl = np . reshape ( np . array ( ccl , dtype = np . int64 ) , [ n , dim + 2 ] ) ccl [ : , - 1 ] = np . mod ( ccl [ : , - 1 ] , coeff ) if doing_permutation : # Retain original indices in the point cloud ccl [ : , 0 : - 1 ] = idx_perm [ ccl [ : , 0 : - 1 ] ] cocycles [ dim ] . append ( ccl ) ret = { "dgms" : dgms , "cocycles" : cocycles , "num_edges" : res [ "num_edges" ] , "dperm2all" : dperm2all , "idx_perm" : idx_perm , "r_cover" : r_cover , } return ret