summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cython/CONVENTIONS9
-rwxr-xr-xsrc/cython/example/alpha_complex_example.py10
-rwxr-xr-xsrc/cython/example/mini_simplex_tree_example.py3
-rwxr-xr-xsrc/cython/example/rips_complex_example.py4
-rwxr-xr-xsrc/cython/example/simplex_tree_example.py9
-rw-r--r--src/cython/src/cpp/Persistent_cohomology_interface.h55
-rw-r--r--src/cython/src/cython/alpha_complex.pyx39
-rw-r--r--src/cython/src/cython/mini_simplex_tree.pyx41
-rw-r--r--src/cython/src/cython/rips_complex.pyx39
-rw-r--r--src/cython/src/cython/simplex_tree.pyx40
10 files changed, 204 insertions, 45 deletions
diff --git a/src/cython/CONVENTIONS b/src/cython/CONVENTIONS
new file mode 100644
index 00000000..804e97f3
--- /dev/null
+++ b/src/cython/CONVENTIONS
@@ -0,0 +1,9 @@
+Gudhi is following PEP8 conventions.
+
+Please refer to:
+https://www.python.org/dev/peps/pep-0008/
+
+A summary:
+ - modules (filenames) should have short, all-lowercase names, and they can contain underscores.
+ - packages (directories) should have short, all-lowercase names, preferably without underscores.
+ - classes should use the CapWords convention. \ No newline at end of file
diff --git a/src/cython/example/alpha_complex_example.py b/src/cython/example/alpha_complex_example.py
index 6996b692..37c04f23 100755
--- a/src/cython/example/alpha_complex_example.py
+++ b/src/cython/example/alpha_complex_example.py
@@ -66,6 +66,12 @@ print("coface([0], 1)=", alpha_complex.get_coface_tree([0], 1))
print("point[0]=", alpha_complex.get_point(0))
print("point[5]=", alpha_complex.get_point(5))
+print("betti_numbers()=")
+print(alpha_complex.betti_numbers())
+
alpha_complex.initialize_filtration()
-print("persistence(2)=", alpha_complex.persistence(homology_coeff_field=2,
- min_persistence=0))
+print("persistence(homology_coeff_field=2, min_persistence=0)=")
+print(alpha_complex.persistence(homology_coeff_field=2, min_persistence=0))
+
+print("betti_numbers()=")
+print(alpha_complex.betti_numbers())
diff --git a/src/cython/example/mini_simplex_tree_example.py b/src/cython/example/mini_simplex_tree_example.py
index 0461a1df..d7189ddf 100755
--- a/src/cython/example/mini_simplex_tree_example.py
+++ b/src/cython/example/mini_simplex_tree_example.py
@@ -55,7 +55,8 @@ mini_st.set_dimension(2)
# initialize_filtration required before plain_homology
mini_st.initialize_filtration()
-print("plain_homology(2)=", mini_st.plain_homology(2))
+print("persistence(homology_coeff_field=2)=")
+print(mini_st.persistence(homology_coeff_field=2))
edge02 = [0, 2]
if mini_st.find(edge02):
diff --git a/src/cython/example/rips_complex_example.py b/src/cython/example/rips_complex_example.py
index eba3f298..449ea2b3 100755
--- a/src/cython/example/rips_complex_example.py
+++ b/src/cython/example/rips_complex_example.py
@@ -37,5 +37,5 @@ print("filtered_tree=", rips.get_filtered_tree())
print("star([0])=", rips.get_star_tree([0]))
print("coface([0], 1)=", rips.get_coface_tree([0], 1))
-print("persistence(2)=", rips.persistence(homology_coeff_field=2,
- min_persistence=0))
+print("persistence(homology_coeff_field=2, min_persistence=0)=")
+print(rips.persistence(homology_coeff_field=2, min_persistence=0))
diff --git a/src/cython/example/simplex_tree_example.py b/src/cython/example/simplex_tree_example.py
index bdaabca2..45d57c53 100755
--- a/src/cython/example/simplex_tree_example.py
+++ b/src/cython/example/simplex_tree_example.py
@@ -2,8 +2,6 @@
import gudhi
-st = gudhi.SimplexTree()
-
"""This file is part of the Gudhi Library. The Gudhi library
(Geometric Understanding in Higher Dimensions) is a generic C++
library for computational topology.
@@ -32,6 +30,9 @@ __license__ = "GPL v3"
print("#####################################################################")
print("SimplexTree creation from insertion")
+
+st = gudhi.SimplexTree()
+
if st.insert([0, 1]):
print("Inserted !!")
else:
@@ -64,5 +65,5 @@ print("skeleton_tree[2]=", st.get_skeleton_tree(2))
print("skeleton_tree[1]=", st.get_skeleton_tree(1))
print("skeleton_tree[0]=", st.get_skeleton_tree(0))
-print("persistence(2)=", st.persistence(homology_coeff_field=2,
- min_persistence=0))
+print("persistence(homology_coeff_field=2, min_persistence=0)=")
+print(st.persistence(homology_coeff_field=2, min_persistence=0))
diff --git a/src/cython/src/cpp/Persistent_cohomology_interface.h b/src/cython/src/cpp/Persistent_cohomology_interface.h
index adfca638..53aea58e 100644
--- a/src/cython/src/cpp/Persistent_cohomology_interface.h
+++ b/src/cython/src/cpp/Persistent_cohomology_interface.h
@@ -25,19 +25,62 @@
#include <gudhi/Persistent_cohomology.h>
+#include <vector>
+#include <utility> // for std::pair
+
namespace Gudhi {
template<class FilteredComplex>
class Persistent_cohomology_interface : public
-persistent_cohomology::Persistent_cohomology<FilteredComplex,persistent_cohomology::Field_Zp> {
+persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp> {
+ private:
+ /*
+ * Compare two intervals by dimension, then by length.
+ */
+ struct cmp_intervals_by_dim_then_length {
+
+ explicit cmp_intervals_by_dim_then_length(FilteredComplex * sc)
+ : sc_(sc) { }
+
+ template<typename Persistent_interval>
+ bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) {
+ if (sc_->dimension(get < 0 > (p1)) == sc_->dimension(get < 0 > (p2)))
+ return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1))
+ > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2)));
+ else
+ return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2)));
+ }
+ FilteredComplex* sc_;
+ };
+
public:
+
Persistent_cohomology_interface(FilteredComplex* stptr)
- : persistent_cohomology::Persistent_cohomology<FilteredComplex,persistent_cohomology::Field_Zp>(*stptr) { }
- void get_persistence(int homology_coeff_field, double min_persistence) {
- persistent_cohomology::Persistent_cohomology<FilteredComplex,persistent_cohomology::Field_Zp>::init_coefficients(homology_coeff_field);
- persistent_cohomology::Persistent_cohomology<FilteredComplex,persistent_cohomology::Field_Zp>::compute_persistent_cohomology(min_persistence);
- persistent_cohomology::Persistent_cohomology<FilteredComplex,persistent_cohomology::Field_Zp>::output_diagram();
+ : persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>(*stptr),
+ stptr_(stptr) { }
+
+ std::vector<std::pair<int, std::pair<double, double>>> get_persistence(int homology_coeff_field, double min_persistence) {
+ persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::init_coefficients(homology_coeff_field);
+ persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::compute_persistent_cohomology(min_persistence);
+
+ // Custom sort and output persistence
+ cmp_intervals_by_dim_then_length cmp(stptr_);
+ auto persistent_pairs = persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::get_persistent_pairs();
+ std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp);
+
+ std::vector<std::pair<int, std::pair<double, double>>> persistence;
+ for (auto pair : persistent_pairs) {
+ persistence.push_back(std::make_pair(stptr_->dimension(get<0>(pair)),
+ std::make_pair(stptr_->filtration(get<0>(pair)),
+ stptr_->filtration(get<1>(pair)))));
+ }
+ return persistence;
+
}
+
+ private:
+ // A copy
+ FilteredComplex* stptr_;
};
diff --git a/src/cython/src/cython/alpha_complex.pyx b/src/cython/src/cython/alpha_complex.pyx
index a06134c8..5df7a659 100644
--- a/src/cython/src/cython/alpha_complex.pyx
+++ b/src/cython/src/cython/alpha_complex.pyx
@@ -53,12 +53,16 @@ cdef extern from "Alpha_complex_interface.h" namespace "Gudhi":
cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi":
cdef cppclass Alpha_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::alphacomplex::Alpha_complex< CGAL::Epick_d< CGAL::Dynamic_dimension_tag > >>":
Alpha_complex_persistence_interface(Alpha_complex_interface * st)
- void get_persistence(int homology_coeff_field, double min_persistence)
+ vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence)
+ vector[int] betti_numbers()
+ vector[int] persistent_betti_numbers(double from_value, double to_value)
# AlphaComplex python interface
cdef class AlphaComplex:
cdef Alpha_complex_interface * thisptr
+ cdef Alpha_complex_persistence_interface * pcohptr
+
def __cinit__(self, points=None, max_alpha_square=float('inf')):
if points is not None:
self.thisptr = new Alpha_complex_interface(points,
@@ -67,6 +71,8 @@ cdef class AlphaComplex:
def __dealloc__(self):
if self.thisptr != NULL:
del self.thisptr
+ if self.pcohptr != NULL:
+ del self.pcohptr
def get_filtration(self):
return self.thisptr.filtration()
@@ -163,9 +169,28 @@ cdef class AlphaComplex:
return point
def persistence(self, homology_coeff_field=11, min_persistence=0):
- cdef Alpha_complex_persistence_interface * pcohptr \
- = new Alpha_complex_persistence_interface(self.thisptr)
- if pcohptr != NULL:
- pcohptr.get_persistence(homology_coeff_field, min_persistence)
- del pcohptr
- return 5
+ if self.pcohptr != NULL:
+ del self.pcohptr
+ self.pcohptr = new Alpha_complex_persistence_interface(self.thisptr)
+ cdef vector[pair[int, pair[double, double]]] persistence_result
+ if self.pcohptr != NULL:
+ persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence)
+ return persistence_result
+
+ def betti_numbers(self):
+ cdef vector[int] bn_result
+ if self.pcohptr != NULL:
+ bn_result = self.pcohptr.betti_numbers()
+ else:
+ print("betti_numbers function requires persistence function"
+ " to be launched first.")
+ return bn_result
+
+ def persistent_betti_numbers(self, from_value, to_value):
+ cdef vector[int] pbn_result
+ if self.pcohptr != NULL:
+ pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value)
+ else:
+ print("persistent_betti_numbers function requires persistence function"
+ " to be launched first.")
+ return pbn_result
diff --git a/src/cython/src/cython/mini_simplex_tree.pyx b/src/cython/src/cython/mini_simplex_tree.pyx
index b836fb88..a5077820 100644
--- a/src/cython/src/cython/mini_simplex_tree.pyx
+++ b/src/cython/src/cython/mini_simplex_tree.pyx
@@ -55,18 +55,24 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi":
cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi":
cdef cppclass Mini_simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_mini>>":
Mini_simplex_tree_persistence_interface(Simplex_tree_interface_mini * st)
- void get_persistence(int homology_coeff_field, double min_persistence)
+ vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence)
+ vector[int] betti_numbers()
+ vector[int] persistent_betti_numbers(double from_value, double to_value)
# MiniSimplexTree python interface
cdef class MiniSimplexTree:
cdef Simplex_tree_interface_mini * thisptr
+ cdef Mini_simplex_tree_persistence_interface * pcohptr
+
def __cinit__(self):
self.thisptr = new Simplex_tree_interface_mini()
def __dealloc__(self):
if self.thisptr != NULL:
del self.thisptr
+ if self.pcohptr != NULL:
+ del self.pcohptr
def get_filtration(self):
return self.thisptr.filtration()
@@ -158,10 +164,29 @@ cdef class MiniSimplexTree:
def remove_maximal_simplex(self, simplex):
self.thisptr.remove_maximal_simplex(simplex)
- def plain_homology(self, homology_coeff_field=11):
- cdef Mini_simplex_tree_persistence_interface * pcohptr \
- = new Mini_simplex_tree_persistence_interface(self.thisptr)
- if pcohptr != NULL:
- pcohptr.get_persistence(homology_coeff_field, 0)
- del pcohptr
- return 5
+ def persistence(self, homology_coeff_field=11):
+ if self.pcohptr != NULL:
+ del self.pcohptr
+ self.pcohptr = new Mini_simplex_tree_persistence_interface(self.thisptr)
+ cdef vector[pair[int, pair[double, double]]] persistence_result
+ if self.pcohptr != NULL:
+ persistence_result = self.pcohptr.get_persistence(homology_coeff_field, 0)
+ return persistence_result
+
+ def betti_numbers(self):
+ cdef vector[int] bn_result
+ if self.pcohptr != NULL:
+ bn_result = self.pcohptr.betti_numbers()
+ else:
+ print("betti_numbers function requires persistence function"
+ " to be launched first.")
+ return bn_result
+
+ def persistent_betti_numbers(self, from_value, to_value):
+ cdef vector[int] pbn_result
+ if self.pcohptr != NULL:
+ pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value)
+ else:
+ print("persistent_betti_numbers function requires persistence function"
+ " to be launched first.")
+ return pbn_result
diff --git a/src/cython/src/cython/rips_complex.pyx b/src/cython/src/cython/rips_complex.pyx
index 3ca890d9..d01f79cb 100644
--- a/src/cython/src/cython/rips_complex.pyx
+++ b/src/cython/src/cython/rips_complex.pyx
@@ -57,12 +57,16 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi":
cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi":
cdef cppclass Rips_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>":
Rips_complex_persistence_interface(Rips_complex_interface * st)
- void get_persistence(int homology_coeff_field, double min_persistence)
+ vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence)
+ vector[int] betti_numbers()
+ vector[int] persistent_betti_numbers(double from_value, double to_value)
# RipsComplex python interface
cdef class RipsComplex:
cdef Rips_complex_interface * thisptr
+ cdef Rips_complex_persistence_interface * pcohptr
+
def __cinit__(self, points=None, max_dimension=3,
max_edge_length=float('inf')):
self.thisptr = new Rips_complex_interface()
@@ -74,6 +78,8 @@ cdef class RipsComplex:
def __dealloc__(self):
if self.thisptr != NULL:
del self.thisptr
+ if self.pcohptr != NULL:
+ del self.pcohptr
def get_filtration(self):
return self.thisptr.filtration()
@@ -166,9 +172,28 @@ cdef class RipsComplex:
self.thisptr.remove_maximal_simplex(simplex)
def persistence(self, homology_coeff_field=11, min_persistence=0):
- cdef Rips_complex_persistence_interface * pcohptr \
- = new Rips_complex_persistence_interface(self.thisptr)
- if pcohptr != NULL:
- pcohptr.get_persistence(homology_coeff_field, min_persistence)
- del pcohptr
- return 5
+ if self.pcohptr != NULL:
+ del self.pcohptr
+ self.pcohptr = new Rips_complex_persistence_interface(self.thisptr)
+ cdef vector[pair[int, pair[double, double]]] persistence_result
+ if self.pcohptr != NULL:
+ persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence)
+ return persistence_result
+
+ def betti_numbers(self):
+ cdef vector[int] bn_result
+ if self.pcohptr != NULL:
+ bn_result = self.pcohptr.betti_numbers()
+ else:
+ print("betti_numbers function requires persistence function"
+ " to be launched first.")
+ return bn_result
+
+ def persistent_betti_numbers(self, from_value, to_value):
+ cdef vector[int] pbn_result
+ if self.pcohptr != NULL:
+ pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value)
+ else:
+ print("persistent_betti_numbers function requires persistence function"
+ " to be launched first.")
+ return pbn_result
diff --git a/src/cython/src/cython/simplex_tree.pyx b/src/cython/src/cython/simplex_tree.pyx
index e3cdc27b..071b19e3 100644
--- a/src/cython/src/cython/simplex_tree.pyx
+++ b/src/cython/src/cython/simplex_tree.pyx
@@ -55,18 +55,24 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi":
cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi":
cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>":
Simplex_tree_persistence_interface(Simplex_tree_interface_full_featured * st)
- void get_persistence(int homology_coeff_field, double min_persistence)
+ vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence)
+ vector[int] betti_numbers()
+ vector[int] persistent_betti_numbers(double from_value, double to_value)
# SimplexTree python interface
cdef class SimplexTree:
cdef Simplex_tree_interface_full_featured * thisptr
+ cdef Simplex_tree_persistence_interface * pcohptr
+
def __cinit__(self):
self.thisptr = new Simplex_tree_interface_full_featured()
def __dealloc__(self):
if self.thisptr != NULL:
del self.thisptr
+ if self.pcohptr != NULL:
+ del self.pcohptr
def get_filtration(self):
return self.thisptr.filtration()
@@ -159,10 +165,28 @@ cdef class SimplexTree:
self.thisptr.remove_maximal_simplex(simplex)
def persistence(self, homology_coeff_field=11, min_persistence=0):
- cdef Simplex_tree_persistence_interface * pcohptr \
- = new Simplex_tree_persistence_interface(self.thisptr)
- if pcohptr != NULL:
- pcohptr.get_persistence(homology_coeff_field, min_persistence)
- del pcohptr
- return 5
-
+ if self.pcohptr != NULL:
+ del self.pcohptr
+ self.pcohptr = new Simplex_tree_persistence_interface(self.thisptr)
+ cdef vector[pair[int, pair[double, double]]] persistence_result
+ if self.pcohptr != NULL:
+ persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence)
+ return persistence_result
+
+ def betti_numbers(self):
+ cdef vector[int] bn_result
+ if self.pcohptr != NULL:
+ bn_result = self.pcohptr.betti_numbers()
+ else:
+ print("betti_numbers function requires persistence function"
+ " to be launched first.")
+ return bn_result
+
+ def persistent_betti_numbers(self, from_value, to_value):
+ cdef vector[int] pbn_result
+ if self.pcohptr != NULL:
+ pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value)
+ else:
+ print("persistent_betti_numbers function requires persistence function"
+ " to be launched first.")
+ return pbn_result