Example #1
0
    def construct_rips(self, p):
        if self.pts is not None:
            rips_complex = gudhi.RipsComplex(points=self.pts,
                                             max_edge_length=self.epsilon)
        if self.dm is not None:
            rips_complex = gudhi.RipsComplex(distance_matrix=self.dm,
                                             max_edge_length=self.epsilon)
        simplex_tree = rips_complex.create_simplex_tree(max_dimension=p + 1)
        val = simplex_tree.get_filtration()
        simplices = set()
        for v in val:
            simplices.add(tuple(v[0]))

        return simplices
def landscape_at_t(data,
                   t,
                   window=-1,
                   dim=0,
                   nbld=3,
                   resolution=500,
                   length_max=0.3):
    """
    data: numpy array of shape (d, T) where T: number of timesteps, d: number of dimensions.
    """
    if window < 0:
        # select all points up to t
        data_t = data[:, :t]
    else:
        # select points in a sliding window
        data_t = data[:, np.max([t - window, 0]):t]

    rips_complex = gd.RipsComplex(data_t, max_edge_length=length_max)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=dim + 1)
    diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0)

    persistence_intervals = simplex_tree.persistence_intervals_in_dimension(
        dim)
    landscapes = landscapes_approx(persistence_intervals, 0, length_max,
                                   resolution, nbld)

    return landscapes, np.arange(0, length_max, length_max / resolution)
Example #3
0
def rips_complex(pts, max_diameter, dimension = 2):
    sc = gd.RipsComplex(points = pts, max_edge_length = max_diameter)
    st = sc.create_simplex_tree(max_dimension = dimension)
    return dict(
        points = pts, 
        simplex_tree = st
    )
Example #4
0
def persistence_pairs(
        batch,
        dim=0,
        device=torch.device('cpu'),
        max_edge_length=np.inf,
        remove_inf=False,
):
    """Use Gudhi to calculate persistence diagrams.

    batch: point clouds input,
    dim: homology dimension (0 for connectivity),
    device: device for torch tensor,
    max_edge_length: threshold on the Vietoris-Rips scale parameter. By default, it builds
    all the simplices in the filtration.
    """
    rips_complex = gd.RipsComplex(batch, max_edge_length=max_edge_length)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=dim + 1)
    simplex_tree.persistence(homology_coeff_field=2, min_persistence=0)
    persistence_intervals = simplex_tree.persistence_intervals_in_dimension(
        dim)

    births = torch.FloatTensor(persistence_intervals[:, 0]).to(device)
    deaths = torch.FloatTensor(persistence_intervals[:, 1]).to(device)

    if remove_inf:
        births = np.ma.masked_invalid(births)
        deaths = np.ma.masked_invalid(deaths)

    return births, deaths
    def build_vr_complex(self, filenameMem, k, n, r, q):
        S = []
        S.extend(self.training)
        S.extend(self.test)
        self.rips = gudhi.RipsComplex(points=S, max_edge_length=float(r))

        self.simplextree = self.rips.create_simplex_tree(max_dimension=q)
Example #6
0
def tgtRipsPdFromTimeSeries(tgtTimeSeries, pcDim, homDim, maxEdgeLen):
    #homDim is a list indicating which homology dimensions are being considered.

    pcPts = convertTde(tgtTimeSeries,dimension=pcDim) #create point cloud (PC) for time series 

    maxDimSimplex = max(homDim) + 1 #considering only sufficient homology dimension 

    rips_complex = gd.RipsComplex(pcPts, max_edge_length=maxEdgeLen)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=maxDimSimplex)

    #PD of the target PC
    diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0)

    print('tgtRaipsPdFromTimeSeries:diag')
    print(diag) 
 
    tgtPD = [] #target PD is a list of tuples, same as Gudhi format.

    maxPers = 0
    maxInd = 0

    for iDiag in diag:
        if (iDiag[0] in homDim):
            birthTime = iDiag[1][0]
            deathTime = iDiag[1][1] 

            if (np.isinf(deathTime)):
                deathTime = maxEdgeLen

            tgtPD.append((iDiag[0],(birthTime,deathTime)))

    return tgtPD
Example #7
0
def rips__filtration_gudhi(D, p, coeff=2, doPlot=False):
    """
    Do the rips filtration, wrapping around the GUDHI library (for comparison)
    :param X: An Nxk matrix of points
    :param p: The order of homology to go up to
    :param coeff: The field coefficient of homology
    :returns Is: A dictionary of persistence diagrams, where Is[k] is \
        the persistence diagram for Hk 
    """
    import gudhi

    rips = gudhi.RipsComplex(distance_matrix=D, max_edge_length=np.inf)
    simplex_tree = rips.create_simplex_tree(max_dimension=p + 1)
    diag = simplex_tree.persistence(homology_coeff_field=coeff,
                                    min_persistence=0)
    if doPlot:
        pplot = gudhi.plot_persistence_diagram(diag)
        pplot.show()
    Is = []
    for i in range(p + 1):
        Is.append([])
    for (i, (b, d)) in diag:
        Is[i].append([b, d])
    for i in range(len(Is)):
        Is[i] = np.array(Is[i])
    return Is
    def build_filtered_simplicial_complex(self):
        S = self.unify_dataset()

        # self.complex = gudhi.AlphaComplex(points=S)
        self.complex = gudhi.RipsComplex(points=S, max_edge_length=8.0)

        self.simplex_tree = self.complex.create_simplex_tree(max_dimension=3)
def create_rips_diag(file):
    dist = pd.read_csv("../distances/our_distances/" + file, index_col=0)
    dist = dist.to_numpy()
    rips_complex = gudhi.RipsComplex(distance_matrix=dist)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
    # simplex_tree.prune_above_filtration(20)
    diag = simplex_tree.persistence()
    list0 = []
    list1 = []
    for d in diag:
        if d[0] == 0:
            list0.append(d[1])
        elif d[0] == 1:
            list1.append(d[1])
    matrix0 = []
    for l in list0:
        if l[1] == float("inf"):
            matrix0.append([l[0], 1])
        else:
            matrix0.append([l[0], l[1]])
    matrix1 = []
    for l in list1:
        if l[1] == float("inf"):
            matrix1.append([l[0], 1])
        else:
            matrix1.append([l[0], l[1]])

    return [matrix0, matrix1]
    def __call__(self, w_size, end_date=None) -> tuple:
        """
        compute persistence and its landscape

        Parameters:
            end_date: the last day used to compute persistence graphs
            w_size: size of the windows for the landscapes computations

        Returns:
            (persistence, landscape)
        """
        if end_date is not None:
            self.verify_date(end_date)
            idx = self.df.index.get_loc(end_date)
        else:
            idx = self.df.index.shape[0]
        self.verify_w_size(idx, w_size)

        array_window = self.df.iloc[idx - w_size + 1:idx + 1, :].values
        rips_complex = gd.RipsComplex(points=array_window)
        simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)

        diagram = simplex_tree.persistence(min_persistence=0)
        x_max = self.find_x_max(diagram)
        land = self.persitence_landscape(diagram, 1, 0, x_max, 1000, 1)

        return diagram, land
Example #11
0
def dist2PD(distance_matrix,max_dim=2,max_edge_length=1):

    rips_complex = gd.RipsComplex(distance_matrix = distance_matrix,max_edge_length=max_edge_length)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=max_dim)        
    diag = simplex_tree.persistence()
    diag = [diag[i] for i in where([s[0]<max_dim for s in diag])[0]]
    return simplex_tree,diag
def test_flag_generators():
    pts = np.array([[0, 0], [0, 1.01], [1, 0], [1.02, 1.03], [100, 0],
                    [100, 3.01], [103, 0], [103.02, 3.03]])
    r = gudhi.RipsComplex(pts, max_edge_length=4)
    st = r.create_simplex_tree(max_dimension=50)
    st.persistence()
    g = st.flag_persistence_generators()
    assert np.array_equal(
        g[0],
        [[2, 2, 0], [1, 1, 0], [3, 3, 1], [6, 6, 4], [5, 5, 4], [7, 7, 5]])
    assert len(g[1]) == 1
    assert np.array_equal(g[1][0], [[3, 2, 2, 1]])
    assert np.array_equal(g[2], [0, 4])
    assert len(g[3]) == 1
    assert np.array_equal(g[3][0], [[7, 6]])
    # Compare trivial cases (where the simplex is the generator) with persistence_pairs.
    # This still makes assumptions on the order of vertices in a simplex and could be more robust.
    pairs = st.persistence_pairs()
    assert {tuple(i)
            for i in g[0]} == {(i[0][0], ) + tuple(i[1])
                               for i in pairs
                               if len(i[0]) == 1 and len(i[1]) != 0}
    assert {
        (i[0], i[1])
        for i in g[1][0]
    } == {tuple(i[0])
          for i in pairs if len(i[0]) == 2 and len(i[1]) != 0}
    assert set(
        g[2]) == {i[0][0]
                  for i in pairs if len(i[0]) == 1 and len(i[1]) == 0}
    assert {
        (i[0], i[1])
        for i in g[3][0]
    } == {tuple(i[0])
          for i in pairs if len(i[0]) == 2 and len(i[1]) == 0}
Example #13
0
def TDA_func(distance_matrix, persfilename, skelfilename):
    print('distance matrix size =', distance_matrix.shape)
    rips_complex = gd.RipsComplex(distance_matrix=distance_matrix,
                                  max_edge_length=1.1)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
    print('done creating simplex tree')
    #filtration = simplex_tree.get_filtration()
    skeleton = simplex_tree.get_skeleton(2)
    writeSkeletonToFile(skeleton, skelfilename)
    diag = simplex_tree.persistence()
    pairs = simplex_tree.persistence_pairs()
    fullpersinfo = []
    for pair in pairs:
        #print(pair)
        btime = simplex_tree.filtration(pair[0])
        dtime = simplex_tree.filtration(pair[1])
        #print(btime,dtime)
        try:
            diag.index((0, (btime, dtime)))
            htype = 0
            fullpersinfo.append([htype, btime, dtime, pair])
        except:
            diag.index((1, (btime, dtime)))
            htype = 1
            fullpersinfo.append([htype, btime, dtime, pair])
            #print('couldnt find persistence pair matching birth/death times', pair, (btime,dtime))
    writePersistencePairsToFile(fullpersinfo, persfilename)
    #simplex_tree.write_persistence_diagram(persfilename)
    #print('wrote persistence diagram to',persfilename)
    #print(diag)
    #data_0_dim=np.array([list(diag[i][1]) for i in range(len(diag)) if diag[i][0]==0])
    #data_1_dim=np.array([list(diag[i][1]) for i in range(len(diag)) if diag[i][0]==1])
    return (skeleton, diag, fullpersinfo)
def create_simplex_tree(M, max_d):
    rips_complex = gd.RipsComplex(points=M, max_edge_length=12.0)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
    result_str='Rips complex is of dimension '+repr(simplex_tree.dimension())+''+\
    repr(simplex_tree.num_simplices())+' simplices-'+\
    repr(simplex_tree.num_vertices())+' vertices.'
    return simplex_tree
def compute_persistence(edge_length=max_edge_length, filtration='rips'):
    if filtration not in ('rips', 'alpha'):
        raise ValueError('Please indicate filtration = "rips" or filtration = "alpha"')
    a, b, c, labels = read_data()
    time_series = a + b + c
    simplex_trees = [0] * len(time_series)

    print('Computing persistence diagrams with {} filtration...'.format(filtration))
    for i, ts in enumerate(time_series):
        if not i % 50:
            print('Computing persistence diagram {}/{}'.format(i, len(time_series)))

        if filtration is 'rips':
            cplx = gudhi.RipsComplex(points=ts, max_edge_length=edge_length)
            simplex_tree = cplx.create_simplex_tree(max_dimension=2)

        else:
            cplx = gudhi.AlphaComplex(points=ts)
            simplex_tree = cplx.create_simplex_tree()

        simplex_trees[i] = simplex_tree
        simplex_tree.persistence(persistence_dim_max=False)
        simplex_tree.write_persistence_diagram('intermediary_data/persistence_diagrams/{}'.format(i))

    return simplex_trees
Example #16
0
def pdFromTimeSeries(tgtTimeSeries, pcDim, homDim, maxEdgeLen, tdeSkip = 1, tdeDelay = 1):
    #homDim indicates which homology dimension to consider.

    pcPts = convertTde(tgtTimeSeries, skip = tdeSkip, delay = tdeDelay, dimension = pcDim) #create point cloud (PC) for time series 

    maxDimSimplex = homDim + 1 #considering only sufficient homology dimension 

    rips_complex = gd.RipsComplex(pcPts, max_edge_length=maxEdgeLen)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=maxDimSimplex)

    #PD of the point cloud
    diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0)
 
    tgtPD = [] #target PD is a list of tuples, same as Gudhi format.

    maxPers = 0
    maxInd = 0

    for iDiag in diag:
        if (iDiag[0] == homDim):
            birthTime = iDiag[1][0]
            deathTime = iDiag[1][1] 

            if (np.isinf(deathTime)): #replace inf value with max. edge length
                deathTime = maxEdgeLen

            tgtPD.append((iDiag[0],(birthTime,deathTime)))

    return tgtPD
Example #17
0
def compute_diagram(x, homo_dim=1):
    """
    This function computes the persistence diagram on the basis of the distance matrix
    and the homology dimension
    """
    rips_tree = gudhi.RipsComplex(x).create_simplex_tree(max_dimension=homo_dim)
    rips_diag = rips_tree.persistence()
    return [rips_tree.persistence_intervals_in_dimension(w) for w in range(homo_dim)]
def computePersistenceDiagrams(pointClouds):
    dgms = []
    for i in range(len(pointClouds)):
        rips_complex = gudhi.RipsComplex(points=pointClouds[i])
        simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
        dgm = simplex_tree.persistence()
        dgms.append(dgm)
    return dgms
Example #19
0
def persistent_homology(
    data: np.ndarray,
    plot: bool = False,
    tikzplot: bool = False,
    maxEdgeLength: int = 42,
    maxDimension: int = 10,
    maxAlphaSquare: float = 1e12,
    homologyCoeffField: int = 2,
    minPersistence: float = 0,
    filtration: str = ["alphaComplex", "vietorisRips", "tangential"],
):
    """
        **Create persistence diagram.**

        This function computes the persistent homology of a dataset upon a filtration of a chosen
        simplicial complex. It can be used for plotting or scientific displaying of persistent homology classes.

        + param **data**: data, type `np.ndarray`.
        + param **plot**: whether or not to plot the persistence diagram using matplotlib, type `bool`.
        + param **tikzplot**: whether or not to create a tikz file from persistent homology, type `bool`.
        + param **maxEdgeLength**: maximal edge length of simplicial complex, type `int`.
        + param **maxDimension**: maximal dimension of simplicial complex, type `int`.
        + param **maxAlphaSquare**: alpha square value for Delaunay complex, type `float`.
        + param **homologyCoeffField**: integers, cyclic moduli integers, rationals enumerated, type `int`.
        + param **minPersistence**: minimal persistence of homology class, type `float`.
        + param **filtration**: the used filtration to calculate persistent homology, type `str`.
        + return **np.ndarray**: data points, type `np.ndarray`.
    """
    dataShape = data.shape
    elementSize = len(data[0].flatten())
    reshapedData = data[0].reshape((int(elementSize / 2), 2))

    if filtration == "vietorisRips":
        simComplex = gd.RipsComplex(
            points=reshapedData,
            max_edge_length=maxEdgeLength).create_simplex_tree(
                max_dimension=maxDimension)
    elif filtration == "alphaComplex":
        simComplex = gd.AlphaComplex(points=reshapedData).create_simplex_tree(
            max_alpha_square=maxAlphaSquare)
    elif filtration == "tangential":
        simComplex = gd.AlphaComplex(points=reshapedData,
                                     intrinsic_dimension=len(data.shape) -
                                     1).compute_tangential_complex()

    persistenceDiagram = simComplex.persistence(
        homology_coeff_field=homologyCoeffField,
        min_persistence=minPersistence)

    if plot == True:
        gd.plot_persistence_diagram(persistenceDiagram)
        plt.show()
    elif tikzplot == True:
        gd.plot_persistence_diagram(persistenceDiagram)
        plt.title("Persistence landscape.")
        tikz.save("persistentHomology_" + filtration + ".tex")

    return persistenceDiagram
Example #20
0
 def compute_diagram(_x, homology_dim):
     print('Initializing Rips-Complex')
     rips_complex = gudhi.RipsComplex(_x)
     # print('Computing simplex tree')
     simplex_tree = rips_complex.create_simplex_tree(max_dimension=homology_dim)
     # print('Simplex tree computed')
     print('Computing persistence diagram')
     diag = simplex_tree.persistence()
     return [simplex_tree.persistence_intervals_in_dimension(w) for w in range(homology_dim)]
 def sample_pers(self):
     """
     Subsample from the point cloud and build the Vietoris-Rips complex"""
     sample_pts = gd.pick_n_random_points(self.points,
                                          nb_points=self.sample_size)
     rips = gd.RipsComplex(points=sample_pts,
                           max_edge_length=self.max_edge_length)
     simplex_tree = rips.create_simplex_tree(max_dimension=2)
     pers = simplex_tree.persistence()
     return pers
Example #22
0
def TDA_monitoring(params, x_latent):
    import gudhi
    distance_matrix = np.arccos(np.clip(np.inner(x_latent,x_latent), -0.99, 0.99))
    rips_complex = gudhi.RipsComplex(distance_matrix=distance_matrix)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=params.max_dimension)
    persistent = simplex_tree.persistence()
    diags = [simplex_tree.persistence_intervals_in_dimension(dim) for dim in range(params.max_dimension)]
    diags = [np.array([t for t in diag if not math.isinf(t[1])]) for diag in diags]
    if params.plot:
        gudhi.plot_persistence_diagram(persistent)
        plt.show()
    return diag_entropies(diags[0], mode='vector')
Example #23
0
def process_Dmatrix(dX, max_k, vec_rhos, 
                    process_edgedensity=True, 
                    min_k=1,
                    save_barcodes=False):
    """
    Process a difference (or distance) matrix and return barcode features and betti curve 
    Return a dictionary `bar_feats` (see output of `process_barcodes` function)
    dX: difference (or distance) matrix
    max_k: maximum simplex dimension to calculate persistent homology 
    vec_rhos: vector of edge density (or distance,difference) to consider for betti number/curve calculate, instead of considering everything 
    process_edgedensity: if True [default], convert to edge density; if false, `vec_rhos` should be a sampled distance vector 
    min_k: [default: 1] minimum simplex to process barcodes 
    save_barcodes: if False [defaul] return bar features dictionary outputs from `process_barcodes` with each key as a homology dimension
                    if True, return `{'barfeats': [bar features from process_barcodes], 'barcodes': [barcodes data]}`
    """
    N = dX.shape[0]

    if process_edgedensity:
        # Obtain rhos (i.e. edge density) from distance
        unq_d = np.unique(dX)
        edge_density = np.array([(np.sum(dX <= x) - N)/(N*(N-1)) for x in unq_d])
        dist2rho_dict = {x:y for x,y in zip(unq_d,edge_density)} 
    
    # Create a vectorized local function to process barcodes later on 
    def dist2rho(d):
        # if distance is infinity, density is 1.0 
        # otherwise use the dict 
        if np.isinf(d): 
            return 1.0
        else:
            return dist2rho_dict[d]
    dist2rho_vect = np.vectorize(dist2rho)

    # Create complex and process persistence 
    gd_tree = gd.RipsComplex(distance_matrix = dX).create_simplex_tree(max_dimension = max_k)
    gd_tree.persistence();

    # Process barcodes of dim >= min_k 
    k_range = range(min_k,max_k)
    bars_eachdim = {'B%d' %(k): gd_tree.persistence_intervals_in_dimension(k)
                    for k in k_range}
    
    if process_edgedensity:
        bars_eachdim = {k: dist2rho_vect(v) if len(v) > 0 else []
                        for k,v in bars_eachdim.items()}
    
    bar_feats = {k: process_barcodes(v, vec_rhos)
                 for k,v in bars_eachdim.items()}
    
    if save_barcodes:
        return {'barfeats': bar_feats, 'barcodes': bars_eachdim}
    else:
        return bar_feats
def compute_persistence_landscape(
    data: np.ndarray,
    res: int = 1000,
    persistenceIntervals: int = 1,
    maxAlphaSquare: float = 1e12,
    filtration: str = ["alphaComplex", "vietorisRips", "tangential"],
    maxDimensions: int = 10,
    edgeLength: float = 1,
    plot: bool = False,
    smoothen: bool = False,
    sigma: int = 3,
) -> np.ndarray:
    """
        **A function for computing persistence landscapes for 2D images.**

        This function computes the filtration of a 2D image dataset, the simplicial complex,
        the persistent homology and then returns the persistence landscape as array. It takes
        the resolution of the landscape as parameter, the maximum size for `alphaSquare` and
        options for certain filtrations.

        + param **data**: data set, type `np.ndarray`.
        + param **res**: resolution, default is `1000`, type `int`.
        + param **persistenceIntervals**: interval for persistent homology, default is `1e12`,type `float`.
        + param **maxAlphaSquare**: max. parameter for delaunay expansion, type `float`.
        + param **filtration**: alphaComplex, vietorisRips, cech, delaunay, tangential, type `str`.
        + param **maxDimensions**: only needed for VietorisRips, type `int`.
        + param **edgeLength**: only needed for VietorisRips, type `float`.
        + param **plot**: whether or not to plot, type `bool`.
        + param **smoothen**: whether or not to smoothen the landscapes, type `bool`.
        + param **sigma**: smoothing factor for gaussian mixtures, type `int`.
        + return **landscapeTransformed**: persistence landscape, type `np.ndarray`.
    """

    if filtration == "alphaComplex":
        simComplex = gd.AlphaComplex(points=data).create_simplex_tree(
            max_alpha_square=maxAlphaSquare)
    elif filtration == "vietorisRips":
        simComplex = gd.RipsComplex(
            points=data_A_sample,
            max_edge_length=edgeLength).create_simplex_tree(
                max_dimension=maxDimensions)
    elif filtration == "tangential":
        simComplex = gd.AlphaComplex(points=data,
                                     intrinsic_dimension=len(data.shape) -
                                     1).compute_tangential_complex()

    persistenceDiagram = simComplex.persistence()
    landscape = gd.representations.Landscape(resolution=res)
    landscapeTransformed = landscape.fit_transform(
        [simComplex.persistence_intervals_in_dimension(persistenceIntervals)])

    return landscapeTransformed
Example #25
0
def save_diagram(filename):

    df = pd.read_csv("../distances/our_distances/" + filename, index_col=0)
    df = df.to_numpy()
    rips_complex = gudhi.RipsComplex(distance_matrix=df)
    simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
    # simplex_tree.prune_above_filtration(20)
    diag = simplex_tree.persistence()

    # plt.figure(figsize=(10, 5))
    gudhi.plot_persistence_diagram(diag)
    plt.savefig("../diagrams/our_diagrames/" +
                '.'.join(filename.split('.')[:-1]) + ".png")
Example #26
0
def compute_local_contributions(points,
                                epsilon,
                                simplex_type="rips",
                                verbose=False):
    local_contributions = {}  # dict {filtration: contribution}

    simplex_counter = 0

    # cicle over points
    for idx, p in enumerate(points):

        neigh_of_p = find_neighbours(points, idx, epsilon)

        local_rips_complex = gd.RipsComplex(points=neigh_of_p,
                                            max_edge_length=epsilon)
        simplex_tree = local_rips_complex.create_simplex_tree(
            max_dimension=len(neigh_of_p) - 1)

        star = simplex_tree.get_star(
            [0])  # the first element of the simplex tree is the point [i]
        # return list of tuples (simplex, filtration)

        # if the simplex is made by only one vertex, get_star returns the empty list,
        # we need to manually add the single vertex contribution
        if not star:
            star = [([0], 0.0)]

        for simplex, filtration in star:
            contribution = (-1)**(
                len(simplex) - 1
            )  # len(simplex) - 1 = dimension of the simplex
            # store the contribution at the right filtration value
            local_contributions[filtration] = local_contributions.get(
                filtration, 0) + contribution

            simplex_counter += 1

    # remove the contributions that are 0
    to_del = []
    for key in local_contributions:
        if local_contributions[key] == 0:
            to_del.append(key)

    for key in to_del:
        del local_contributions[key]

    # convert the dict into a list, sort it according to the filtration and return it
    return sorted(list(local_contributions.items()),
                  key=lambda x: x[0]), simplex_counter
def _compute_pd(X, hdim=1, min_persistence=0.0001, mode="alpha", rotate=False):
    if mode == "alpha":
        ac = gd.AlphaComplex(points=X)
        st = ac.create_simplex_tree()
    elif mode == "rips":
        ac = gd.RipsComplex(points=X)
        st = ac.create_simplex_tree(max_dimension=2)
    pers = st.persistence(min_persistence=min_persistence)
    h1 = st.persistence_intervals_in_dimension(hdim)
    if mode == "alpha":
        h1 = np.sqrt(np.array(h1))
        if rotate:
            h1[:, 1] = h1[:, 1] - h1[:, 0]
        return h1
    else:
        return np.array(h1) / 2  # to make it comparable with Cech
    def compute_persistence(self, distances, dimension = 2, spy = False):
        """
        Function for computing the persistent homology from the given distance matrix. Once the birth and death
        times are calculated, we look at the difference between the lifetimes of two longest living cycles of given
        dimension as well as the lifetimes of longest and shortest living cycles which should recover the 
        `self.manifold`.
        
        Parameters
        ============
        
        distances: array , `self.N x self.N`
            Distance matrix obtained from `make_distance_matrix`.
            
        dimension: int
            Maximum dimension that the simplicial complex will be built. Accordingly, maximum dimensional 
            topological features are going to be `dimension -1`. Default is 2 suitable for the `Ring` topology, 
            which is a 1-D compact manifold, but should set to 3 if the topology is a 2D-compact manifold.

        spy: bool
            If True, persistence diagram will be shown.
            
        Returns
        ===========
        
        Delta_min: float
            Normalized difference between the lifetimes of longest and and second longest living cycles of 
            dimension `dimension -1`.
        Delta_max: float
            Normalized difference between the lifetimes of longest and shorthes living cycles of dimension
            `dimension -1`.
        """
        rips_complex = gudhi.RipsComplex(distance_matrix = distances/np.max(distances), max_edge_length = 1)
        simplex_tree = rips_complex.create_simplex_tree(max_dimension = dimension)
        persistence = simplex_tree.persistence(min_persistence = 0.0)
        
        if spy: 
            gudhi.plot_persistence_diagram(persistence)

        oned_holes = [(0,0)]
        for i in range(len(persistence)):
            if persistence[i][0] == int(dimension-1):
                oned_holes.append(persistence[i][1])
        oned_holes = np.array(oned_holes)
        persistence_life_times = oned_holes[:,1]-oned_holes[:,0]
        Delta_min = np.sort(persistence_life_times)[-1]-np.sort(persistence_life_times)[-2]
        Delta_max = np.sort(persistence_life_times)[-1]-np.sort(persistence_life_times)[1]
        return(Delta_min, Delta_max)
Example #29
0
def show(count):
    mlab.clf()
    directory = "VR/%02d/" % count
    points = np.loadtxt(directory + "points.csv", delimiter=",")
    (low, up) = _get_threshold(directory + "threshold.txt")
    rc = gudhi.RipsComplex(points, max_edge_length=(low + up) / 2)
    st = rc.create_simplex_tree(max_dimension=2)
    triangles = [s[0] for s in st.get_skeleton(2) if len(s[0]) == 3]
    edges = []
    for s in st.get_skeleton(1):
        e = s[0]
        if len(e) == 2:
            edges.append(points[[e[0], e[1]]])

    mlab.triangular_mesh(points[:, 0], points[:, 1], points[:, 2], triangles)
    for e in edges:
        mlab.plot3d(e[:, 0], e[:, 1], e[:, 2], tube_radius=None)
    def get_bottleneck_distance(self, w_size):
        """Compute bottleneck distance of persistence landscape

        Parameters:
            w_size: size of the windows for the landscapes computations

        Returns:
            bottleneck: bottleneck distance
        """
        last_df = self.load_dataset(f'w{w_size}_bottleneck')
        if last_df is not None:
            bottleneck = last_df['bottleneck'].values.reshape(-1)
            return bottleneck

        length = self.df.shape[0] - w_size
        bottleneck = np.zeros(self.df.shape[0])
        prev_diagram_b = None

        message = f"Compute the bottleneck distance for a window of {w_size} " \
                f"on {length} points\n"
        sys.stdout.write(message + "-" * (len(message) - 1) + '\n')
        sys.stdout.flush()
        pb = ProgressBar(total=length)

        for idx in range(length):
            array_window = self.df.iloc[idx:idx + w_size, :].values
            rips_complex = gd.RipsComplex(points=array_window)
            simplex_tree = rips_complex.create_simplex_tree(max_dimension=2)
            current_diagram = simplex_tree.persistence(min_persistence=0)

            current_diagram_b = []
            for i in range(len(current_diagram)):
                if current_diagram[i][0] == 1:
                    current_diagram_b.append(
                        [current_diagram[i][1][0], current_diagram[i][1][1]])

            if prev_diagram_b != None:
                dist = gd.bottleneck_distance(current_diagram_b,
                                              prev_diagram_b)
                bottleneck[idx + w_size] = dist
            prev_diagram_b = current_diagram_b
            next(pb)

        df = pd.DataFrame({'bottleneck': bottleneck}, columns=['bottleneck'])
        self.save_dataset(df, f'w{w_size}_bottleneck')
        return bottleneck