From 64199fd8037556f135f90102ba8270cccf9d3e60 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 7 Mar 2020 01:08:10 +0100 Subject: persistence generators for lower-star and flag filtrations --- src/python/gudhi/simplex_tree.pyx | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index b18627c4..1c9b9cf1 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -514,3 +514,58 @@ cdef class SimplexTree: else: print("intervals_in_dim function requires persistence function" " to be launched first.") + + def lower_star_persistence_generators(self): + """Assuming this is a lower-star filtration, this function returns the persistence pairs, + where each simplex is replaced with the vertex that gave it its filtration value. + + :returns: first the regular persistence pairs, grouped by dimension, with one vertex per extremity, + and second the essential features, grouped by dimension, with one vertex each + :rtype: Tuple[List[numpy.array[int] of shape (n,2)], List[numpy.array[int] of shape (m,)]] + + :note: intervals_in_dim function requires + :func:`persistence()` + function to be launched first. + """ + if self.pcohptr != NULL: + gen = self.pcohptr.lower_star_generators() + normal = [np_array(d).reshape(-1,2) for d in gen.first] + infinite = [np_array(d) for d in gen.second] + return (normal, infinite) + else: + print("lower_star_persistence_generators() requires that persistence() be called first.") + + def flag_persistence_generators(self): + """Assuming this is a flag complex, this function returns the persistence pairs, + where each simplex is replaced with the vertices of the edges that gave it its filtration value. + + :returns: first the regular persistence pairs of dimension 0, with one vertex for birth and two for death; + then the other regular persistence pairs, grouped by dimension, with 2 vertices per extremity; + then the connected components, with one vertex each; + finally the other essential features, grouped by dimension, with 2 vertices for birth. + :rtype: Tuple[List[numpy.array[int] of shape (n,3)], List[numpy.array[int] of shape (m,4)], List[numpy.array[int] of shape (l,)], List[numpy.array[int] of shape (k,2)]] + + :note: intervals_in_dim function requires + :func:`persistence()` + function to be launched first. + """ + if self.pcohptr != NULL: + gen = self.pcohptr.flag_generators() + if len(gen.first) == 0: + normal0 = np_array([]) + normals = np_array([]) + else: + l = iter(gen.first) + normal0 = np_array(next(l)).reshape(-1,3) + normals = [np_array(d).reshape(-1,4) for d in l] + if len(gen.second) == 0: + infinite0 = np_array([]) + infinites = np_array([]) + else: + l = iter(gen.second) + infinite0 = np_array(next(l)) + infinites = [np_array(d).reshape(-1,3) for d in l] + + return (normal0, normals, infinite0, infinites) + else: + print("lower_star_persistence_generators() requires that persistence() be called first.") -- cgit v1.2.3 From 35e08b30836fb0c419c0377eaf51d2a3b16e7670 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 7 Mar 2020 14:05:05 +0100 Subject: min_persistence for generators --- src/python/gudhi/simplex_tree.pxd | 4 +-- src/python/gudhi/simplex_tree.pyx | 36 +++++++++++++--------- .../include/Persistent_cohomology_interface.h | 10 ++++-- 3 files changed, 30 insertions(+), 20 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 4e435c67..53e2bbc9 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -53,5 +53,5 @@ cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": vector[pair[double,double]] intervals_in_dimension(int dimension) void write_output_diagram(string diagram_file_name) vector[pair[vector[int], vector[int]]] persistence_pairs() - pair[vector[vector[int]], vector[vector[int]]] lower_star_generators() - pair[vector[vector[int]], vector[vector[int]]] flag_generators() + pair[vector[vector[int]], vector[vector[int]]] lower_star_generators(double) + pair[vector[vector[int]], vector[vector[int]]] flag_generators(double) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 1c9b9cf1..3f582ac9 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -395,7 +395,7 @@ cdef class SimplexTree: :param min_persistence: The minimum persistence value to take into account (strictly greater than min_persistence). Default value is 0.0. - Sets min_persistence to -1.0 to see all values. + Set min_persistence to -1.0 to see all values. :type min_persistence: float. :param persistence_dim_max: If true, the persistent homology for the maximal dimension in the complex is computed. If false, it is @@ -515,42 +515,48 @@ cdef class SimplexTree: print("intervals_in_dim function requires persistence function" " to be launched first.") - def lower_star_persistence_generators(self): + def lower_star_persistence_generators(self, min_persistence=0.): """Assuming this is a lower-star filtration, this function returns the persistence pairs, where each simplex is replaced with the vertex that gave it its filtration value. - :returns: first the regular persistence pairs, grouped by dimension, with one vertex per extremity, + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Set min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: First the regular persistence pairs, grouped by dimension, with one vertex per extremity, and second the essential features, grouped by dimension, with one vertex each :rtype: Tuple[List[numpy.array[int] of shape (n,2)], List[numpy.array[int] of shape (m,)]] - :note: intervals_in_dim function requires - :func:`persistence()` - function to be launched first. + :note: lower_star_persistence_generators requires that `persistence()` be called first. """ if self.pcohptr != NULL: - gen = self.pcohptr.lower_star_generators() + gen = self.pcohptr.lower_star_generators(min_persistence) normal = [np_array(d).reshape(-1,2) for d in gen.first] infinite = [np_array(d) for d in gen.second] return (normal, infinite) else: print("lower_star_persistence_generators() requires that persistence() be called first.") - def flag_persistence_generators(self): + def flag_persistence_generators(self, min_persistence=0.): """Assuming this is a flag complex, this function returns the persistence pairs, where each simplex is replaced with the vertices of the edges that gave it its filtration value. - :returns: first the regular persistence pairs of dimension 0, with one vertex for birth and two for death; + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Set min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: First the regular persistence pairs of dimension 0, with one vertex for birth and two for death; then the other regular persistence pairs, grouped by dimension, with 2 vertices per extremity; then the connected components, with one vertex each; finally the other essential features, grouped by dimension, with 2 vertices for birth. - :rtype: Tuple[List[numpy.array[int] of shape (n,3)], List[numpy.array[int] of shape (m,4)], List[numpy.array[int] of shape (l,)], List[numpy.array[int] of shape (k,2)]] + :rtype: Tuple[numpy.array[int] of shape (n,3), List[numpy.array[int] of shape (m,4)], numpy.array[int] of shape (l,), List[numpy.array[int] of shape (k,2)]] - :note: intervals_in_dim function requires - :func:`persistence()` - function to be launched first. + :note: flag_persistence_generators requires that `persistence()` be called first. """ if self.pcohptr != NULL: - gen = self.pcohptr.flag_generators() + gen = self.pcohptr.flag_generators(min_persistence) if len(gen.first) == 0: normal0 = np_array([]) normals = np_array([]) @@ -568,4 +574,4 @@ cdef class SimplexTree: return (normal0, normals, infinite0, infinites) else: - print("lower_star_persistence_generators() requires that persistence() be called first.") + print("flag_persistence_generators() requires that persistence() be called first.") diff --git a/src/python/include/Persistent_cohomology_interface.h b/src/python/include/Persistent_cohomology_interface.h index 6e9aac52..8e721fc0 100644 --- a/src/python/include/Persistent_cohomology_interface.h +++ b/src/python/include/Persistent_cohomology_interface.h @@ -95,11 +95,10 @@ persistent_cohomology::Persistent_cohomology>, std::vector>> Generators; - Generators lower_star_generators() { + Generators lower_star_generators(double min_persistence) { Generators out; // diags[i] should be interpreted as vector> auto& diags = out.first; @@ -108,6 +107,8 @@ persistent_cohomology::Persistent_cohomology(pair); auto t = std::get<1>(pair); + if(stptr_->filtration(t) - stptr_->filtration(s) <= min_persistence) + continue; int dim = stptr_->dimension(s); auto v = stptr_->vertex_with_same_filtration(s); if(t == stptr_->null_simplex()) { @@ -123,7 +124,8 @@ persistent_cohomology::Persistent_cohomology> and other diags[i] as vector> auto& diags = out.first; @@ -132,6 +134,8 @@ persistent_cohomology::Persistent_cohomology(pair); auto t = std::get<1>(pair); + if(stptr_->filtration(t) - stptr_->filtration(s) <= min_persistence) + continue; int dim = stptr_->dimension(s); bool infinite = t == stptr_->null_simplex(); if(infinite) { -- cgit v1.2.3 From 55c1385419edd4e152df219dfff596d2631367f1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 8 Mar 2020 11:15:04 +0100 Subject: Typo in shape of array --- src/python/gudhi/simplex_tree.pyx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 3f582ac9..d5f642d1 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -8,6 +8,7 @@ # - YYYY/MM Author: Description of the modification from libc.stdint cimport intptr_t +import numpy from numpy import array as np_array cimport simplex_tree @@ -558,19 +559,19 @@ cdef class SimplexTree: if self.pcohptr != NULL: gen = self.pcohptr.flag_generators(min_persistence) if len(gen.first) == 0: - normal0 = np_array([]) - normals = np_array([]) + normal0 = numpy.empty((0,3)) + normals = [] else: l = iter(gen.first) normal0 = np_array(next(l)).reshape(-1,3) normals = [np_array(d).reshape(-1,4) for d in l] if len(gen.second) == 0: - infinite0 = np_array([]) - infinites = np_array([]) + infinite0 = numpy.empty(0) + infinites = [] else: l = iter(gen.second) infinite0 = np_array(next(l)) - infinites = [np_array(d).reshape(-1,3) for d in l] + infinites = [np_array(d).reshape(-1,2) for d in l] return (normal0, normals, infinite0, infinites) else: -- cgit v1.2.3 From ec4a9583adaa73c01b05a4b30425581ed7256379 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Mar 2020 14:50:53 +0100 Subject: Remove min_persistence from generators It is supposed to be handled in persistence() already. --- src/python/CMakeLists.txt | 1 + src/python/gudhi/simplex_tree.pxd | 4 ++-- src/python/gudhi/simplex_tree.pyx | 18 ++++-------------- src/python/include/Persistent_cohomology_interface.h | 8 ++------ src/python/test/test_simplex_generators.py | 2 +- 5 files changed, 10 insertions(+), 23 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index f00966a5..fb219884 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -374,6 +374,7 @@ if(PYTHONINTERP_FOUND) ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py) add_gudhi_py_test(test_simplex_tree) + add_gudhi_py_test(test_simplex_generators) # Witness add_test(NAME witness_complex_from_nearest_landmark_table_py_test diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 44789365..4038b41d 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -75,5 +75,5 @@ cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": vector[pair[double,double]] intervals_in_dimension(int dimension) void write_output_diagram(string diagram_file_name) vector[pair[vector[int], vector[int]]] persistence_pairs() - pair[vector[vector[int]], vector[vector[int]]] lower_star_generators(double) - pair[vector[vector[int]], vector[vector[int]]] flag_generators(double) + pair[vector[vector[int]], vector[vector[int]]] lower_star_generators() + pair[vector[vector[int]], vector[vector[int]]] flag_generators() diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index faa9f9d8..beb40bc4 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -526,15 +526,10 @@ cdef class SimplexTree: print("intervals_in_dim function requires persistence function" " to be launched first.") - def lower_star_persistence_generators(self, min_persistence=0.): + def lower_star_persistence_generators(self): """Assuming this is a lower-star filtration, this function returns the persistence pairs, where each simplex is replaced with the vertex that gave it its filtration value. - :param min_persistence: The minimum persistence value to take into - account (strictly greater than min_persistence). Default value is - 0.0. - Set min_persistence to -1.0 to see all values. - :type min_persistence: float. :returns: First the regular persistence pairs, grouped by dimension, with one vertex per extremity, and second the essential features, grouped by dimension, with one vertex each :rtype: Tuple[List[numpy.array[int] of shape (n,2)], List[numpy.array[int] of shape (m,)]] @@ -542,22 +537,17 @@ cdef class SimplexTree: :note: lower_star_persistence_generators requires that `persistence()` be called first. """ if self.pcohptr != NULL: - gen = self.pcohptr.lower_star_generators(min_persistence) + gen = self.pcohptr.lower_star_generators() normal = [np_array(d).reshape(-1,2) for d in gen.first] infinite = [np_array(d) for d in gen.second] return (normal, infinite) else: print("lower_star_persistence_generators() requires that persistence() be called first.") - def flag_persistence_generators(self, min_persistence=0.): + def flag_persistence_generators(self): """Assuming this is a flag complex, this function returns the persistence pairs, where each simplex is replaced with the vertices of the edges that gave it its filtration value. - :param min_persistence: The minimum persistence value to take into - account (strictly greater than min_persistence). Default value is - 0.0. - Set min_persistence to -1.0 to see all values. - :type min_persistence: float. :returns: First the regular persistence pairs of dimension 0, with one vertex for birth and two for death; then the other regular persistence pairs, grouped by dimension, with 2 vertices per extremity; then the connected components, with one vertex each; @@ -567,7 +557,7 @@ cdef class SimplexTree: :note: flag_persistence_generators requires that `persistence()` be called first. """ if self.pcohptr != NULL: - gen = self.pcohptr.flag_generators(min_persistence) + gen = self.pcohptr.flag_generators() if len(gen.first) == 0: normal0 = numpy.empty((0,3)) normals = [] diff --git a/src/python/include/Persistent_cohomology_interface.h b/src/python/include/Persistent_cohomology_interface.h index 3ce40af5..3074389c 100644 --- a/src/python/include/Persistent_cohomology_interface.h +++ b/src/python/include/Persistent_cohomology_interface.h @@ -100,7 +100,7 @@ persistent_cohomology::Persistent_cohomology>, std::vector>> Generators; - Generators lower_star_generators(double min_persistence) { + Generators lower_star_generators() { Generators out; // diags[i] should be interpreted as vector> auto& diags = out.first; @@ -109,8 +109,6 @@ persistent_cohomology::Persistent_cohomology(pair); auto t = std::get<1>(pair); - if(stptr_->filtration(t) - stptr_->filtration(s) <= min_persistence) - continue; int dim = stptr_->dimension(s); auto v = stptr_->vertex_with_same_filtration(s); if(t == stptr_->null_simplex()) { @@ -128,7 +126,7 @@ persistent_cohomology::Persistent_cohomology> and other diags[i] as vector> auto& diags = out.first; @@ -137,8 +135,6 @@ persistent_cohomology::Persistent_cohomology(pair); auto t = std::get<1>(pair); - if(stptr_->filtration(t) - stptr_->filtration(s) <= min_persistence) - continue; int dim = stptr_->dimension(s); bool infinite = t == stptr_->null_simplex(); if(infinite) { diff --git a/src/python/test/test_simplex_generators.py b/src/python/test/test_simplex_generators.py index efb5f8e3..e3bdc094 100755 --- a/src/python/test/test_simplex_generators.py +++ b/src/python/test/test_simplex_generators.py @@ -37,7 +37,7 @@ def test_lower_star_generators(): st.assign_filtration([1], 2) st.make_filtration_non_decreasing() st.persistence(min_persistence=-1) - g = st.lower_star_persistence_generators(min_persistence=-1) + g = st.lower_star_persistence_generators() assert len(g[0]) == 2 assert np.array_equal(g[0][0], [[0, 0], [3, 0], [1, 1]]) assert np.array_equal(g[0][1], [[1, 1]]) -- cgit v1.2.3 From d5c8dc1ba4d00ead5875b97e164d07f6180526b0 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Mar 2020 20:31:05 +0100 Subject: print -> assert --- src/python/gudhi/simplex_tree.pyx | 47 +++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index beb40bc4..dcf1b46e 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -536,13 +536,11 @@ cdef class SimplexTree: :note: lower_star_persistence_generators requires that `persistence()` be called first. """ - if self.pcohptr != NULL: - gen = self.pcohptr.lower_star_generators() - normal = [np_array(d).reshape(-1,2) for d in gen.first] - infinite = [np_array(d) for d in gen.second] - return (normal, infinite) - else: - print("lower_star_persistence_generators() requires that persistence() be called first.") + assert self.pcohptr != NULL, "lower_star_persistence_generators() requires that persistence() be called first." + gen = self.pcohptr.lower_star_generators() + normal = [np_array(d).reshape(-1,2) for d in gen.first] + infinite = [np_array(d) for d in gen.second] + return (normal, infinite) def flag_persistence_generators(self): """Assuming this is a flag complex, this function returns the persistence pairs, @@ -556,23 +554,20 @@ cdef class SimplexTree: :note: flag_persistence_generators requires that `persistence()` be called first. """ - if self.pcohptr != NULL: - gen = self.pcohptr.flag_generators() - if len(gen.first) == 0: - normal0 = numpy.empty((0,3)) - normals = [] - else: - l = iter(gen.first) - normal0 = np_array(next(l)).reshape(-1,3) - normals = [np_array(d).reshape(-1,4) for d in l] - if len(gen.second) == 0: - infinite0 = numpy.empty(0) - infinites = [] - else: - l = iter(gen.second) - infinite0 = np_array(next(l)) - infinites = [np_array(d).reshape(-1,2) for d in l] - - return (normal0, normals, infinite0, infinites) + assert self.pcohptr != NULL, "flag_persistence_generators() requires that persistence() be called first." + gen = self.pcohptr.flag_generators() + if len(gen.first) == 0: + normal0 = numpy.empty((0,3)) + normals = [] + else: + l = iter(gen.first) + normal0 = np_array(next(l)).reshape(-1,3) + normals = [np_array(d).reshape(-1,4) for d in l] + if len(gen.second) == 0: + infinite0 = numpy.empty(0) + infinites = [] else: - print("flag_persistence_generators() requires that persistence() be called first.") + l = iter(gen.second) + infinite0 = np_array(next(l)) + infinites = [np_array(d).reshape(-1,2) for d in l] + return (normal0, normals, infinite0, infinites) -- cgit v1.2.3