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)
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 )
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)
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
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
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}
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
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
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
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
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
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')
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
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")
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)
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