From b35f3d3dc3225bf12152172d332942e6d7dfc956 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 19 Mar 2018 16:35:00 +0000 Subject: Documentation for Nerve_gic git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/python_nerve_gic_vincent@3297 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3e80b2592386707ac760d0f7cd4bce9d2e9fd7e6 --- src/cython/cython/nerve_gic.pyx | 33 +++++- src/cython/doc/index.rst | 5 + src/cython/doc/nerve_gic_complex_ref.rst | 10 ++ src/cython/doc/nerve_gic_complex_sum.rst | 15 +++ src/cython/doc/nerve_gic_complex_user.rst | 160 ++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/cython/doc/nerve_gic_complex_ref.rst create mode 100644 src/cython/doc/nerve_gic_complex_sum.rst create mode 100644 src/cython/doc/nerve_gic_complex_user.rst (limited to 'src') diff --git a/src/cython/cython/nerve_gic.pyx b/src/cython/cython/nerve_gic.pyx index 2c04cb5e..32c3cd26 100644 --- a/src/cython/cython/nerve_gic.pyx +++ b/src/cython/cython/nerve_gic.pyx @@ -39,6 +39,7 @@ cdef extern from "Nerve_gic_interface.h" namespace "Gudhi": void compute_distribution(int N) double compute_p_value() void compute_PD() + void find_simplices() void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree) bool read_point_cloud(string off_file_name) double set_automatic_resolution() @@ -63,6 +64,9 @@ cdef extern from "Nerve_gic_interface.h" namespace "Gudhi": void set_type(string type) void set_verbose(bool verbose) vector[int] subpopulation(int c) + void write_info() + void plot_DOT() + void plot_OFF() # CoverComplex python interface cdef class CoverComplex: @@ -152,6 +156,11 @@ cdef class CoverComplex: self.thisptr.create_simplex_tree(simplex_tree.thisptr) return simplex_tree + def find_simplices(self): + """Computes the simplices of the simplicial complex. + """ + self.thisptr.find_simplices() + def read_point_cloud(self, off_file): """Reads and stores the input point cloud. @@ -348,7 +357,7 @@ cdef class CoverComplex: :param type: either "GIC" or "Nerve". :type type: string """ - self.thisptr.set_type(type) + self.thisptr.set_type(str.encode(type)) def set_verbose(self, verbose): """Specifies whether the program should display information or not. @@ -365,3 +374,25 @@ cdef class CoverComplex: :rtype: vector[int] :returns: Vector of IDs of data points. """ + return self.thisptr.subpopulation(c) + + def write_info(self): + """Creates a .txt file called SC.txt describing the 1-skeleton, which can + then be plotted with e.g. KeplerMapper. + """ + return self.thisptr.write_info() + + def plot_dot(self): + """Creates a .dot file called SC.dot for neato (part of the graphviz + package) once the simplicial complex is computed to get a visualization of + its 1-skeleton in a .pdf file. + """ + return self.thisptr.plot_DOT() + + def plot_off(self): + """Creates a .off file called SC.off for 3D visualization, which contains + the 2-skeleton of the GIC. This function assumes that the cover has been + computed with Voronoi. If data points are in 1D or 2D, the remaining + coordinates of the points embedded in 3D are set to 0. + """ + return self.thisptr.plot_OFF() diff --git a/src/cython/doc/index.rst b/src/cython/doc/index.rst index 3945d72a..c5e7954f 100644 --- a/src/cython/doc/index.rst +++ b/src/cython/doc/index.rst @@ -36,6 +36,11 @@ Alpha complex .. include:: alpha_complex_sum.rst +Cover complexes +=============== + +.. include:: nerve_gic_complex_sum.rst + Cubical complex =============== diff --git a/src/cython/doc/nerve_gic_complex_ref.rst b/src/cython/doc/nerve_gic_complex_ref.rst new file mode 100644 index 00000000..e24e01fc --- /dev/null +++ b/src/cython/doc/nerve_gic_complex_ref.rst @@ -0,0 +1,10 @@ +================================ +Cover complexes reference manual +================================ + +.. autoclass:: gudhi.CoverComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.CoverComplex.__init__ diff --git a/src/cython/doc/nerve_gic_complex_sum.rst b/src/cython/doc/nerve_gic_complex_sum.rst new file mode 100644 index 00000000..72782c7a --- /dev/null +++ b/src/cython/doc/nerve_gic_complex_sum.rst @@ -0,0 +1,15 @@ +================================================================= =================================== =================================== +:Author: Mathieu Carrière :Introduced in: GUDHI 2.1.0 :Copyright: GPL v3 +:Requires: CGAL :math:`\geq` 4.8.1 +================================================================= =================================== =================================== + ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| .. figure:: | Nerves and Graph Induced Complexes are cover complexes, i.e. | +| ../../doc/Nerve_GIC/gicvisu.jpg | simplicial complexes that provably contain topological information | +| :alt: Graph Induced Complex of a point cloud. | about the input data. They can be computed with a cover of the data, | +| :figclass: align-center | that comes i.e. from the preimage of a family of intervals covering | +| | the image of a scalar-valued function defined on the data. | +| Graph Induced Complex of a point cloud. | | ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| :doc:`nerve_gic_complex_user` | :doc:`nerve_gic_complex_ref` | ++----------------------------------------------------------------+------------------------------------------------------------------------+ diff --git a/src/cython/doc/nerve_gic_complex_user.rst b/src/cython/doc/nerve_gic_complex_user.rst new file mode 100644 index 00000000..249d79f1 --- /dev/null +++ b/src/cython/doc/nerve_gic_complex_user.rst @@ -0,0 +1,160 @@ +Cover complexes user manual +=========================== +Definition +---------- + +.. include:: nerve_gic_complex_sum.rst + +Visualizations of the simplicial complexes can be done with either +neato (from `graphviz `_), +`geomview `_, +`KeplerMapper `_. +Input point clouds are assumed to be +`OFF files `_. + +Covers +------ + +Nerves and Graph Induced Complexes require a cover C of the input point cloud P, +that is a set of subsets of P whose union is P itself. +Very often, this cover is obtained from the preimage of a family of intervals covering +the image of some scalar-valued function f defined on P. This family is parameterized +by its resolution, which can be either the number or the length of the intervals, +and its gain, which is the overlap percentage between consecutive intervals (ordered by their first values). + +Nerves +------ + +Nerve definition +^^^^^^^^^^^^^^^^ + +Assume you are given a cover C of your point cloud P. Then, the Nerve of this cover +is the simplicial complex that has one k-simplex per k-fold intersection of cover elements. +See also `Wikipedia `_. + +.. figure:: + ../../doc/Nerve_GIC/nerve.png + :figclass: align-center + :alt: Nerve of a double torus + + Nerve of a double torus + +Example +^^^^^^^ + +This example builds the Nerve of a point cloud sampled on a 3D human shape (human.off). +The cover C comes from the preimages of intervals (10 intervals with gain 0.3) +covering the height function (coordinate 2), +which are then refined into their connected components using the triangulation of the .OFF file. + +.. testcode:: + + import gudhi + nerve_complex = gudhi.CoverComplex() + nerve_complex.set_verbose(True) + + if (nerve_complex.read_point_cloud(gudhi.__root_source_dir__ + \ + '/data/points/human.off')): + nerve_complex.set_type('Nerve') + nerve_complex.set_color_from_coordinate(2) + nerve_complex.set_function_from_coordinate(2) + nerve_complex.set_graph_from_OFF() + nerve_complex.set_resolution_with_interval_number(10) + nerve_complex.set_gain(0.3) + nerve_complex.set_cover_from_function() + nerve_complex.find_simplices() + nerve_complex.write_info() + simplex_tree = nerve_complex.create_simplex_tree() + nerve_complex.compute_PD() + result_str = 'Nerve is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtration(): + print(filtered_value[0]) + +the program output is: + + Min function value = -0.979672 and Max function value = 0.816414 + Interval 0 = [-0.979672, -0.761576] + Interval 1 = [-0.838551, -0.581967] + Interval 2 = [-0.658942, -0.402359] + Interval 3 = [-0.479334, -0.22275] + Interval 4 = [-0.299725, -0.0431414] + Interval 5 = [-0.120117, 0.136467] + Interval 6 = [0.059492, 0.316076] + Interval 7 = [0.239101, 0.495684] + Interval 8 = [0.418709, 0.675293] + Interval 9 = [0.598318, 0.816414] + Computing preimages... + Computing connected components... + 5 interval(s) in dimension 0: + [-0.909111, 0.0081753] + [-0.171433, 0.367393] + [-0.171433, 0.367393] + [-0.909111, 0.745853] + 0 interval(s) in dimension 1: + +.. testoutput:: + + Nerve is of dimension 1 - 41 simplices - 21 vertices. + [1] + [0] + [4] + [0, 4] + [2] + [1, 2] + [8] + [2, 8] + [5] + [4, 5] + [9] + [8, 9] + [13] + [5, 13] + [14] + [9, 14] + [19] + [13, 19] + [25] + [32] + [20] + [20, 32] + [33] + [25, 33] + [26] + [14, 26] + [19, 26] + [42] + [26, 42] + [34] + [33, 34] + [27] + [20, 27] + [35] + [27, 35] + [34, 35] + [35, 42] + [44] + [35, 44] + [54] + [44, 54] + + +The program also writes a file ../../data/points/human.off_sc.txt. The first +three lines in this file are the location of the input point cloud and the +function used to compute the cover. +The fourth line contains the number of vertices nv and edges ne of the Nerve. +The next nv lines represent the vertices. Each line contains the vertex ID, +the number of data points it contains, and their average color function value. +Finally, the next ne lines represent the edges, characterized by the ID of +their vertices. + +Using KeplerMapper, one can obtain the following visualization: + +.. figure:: + ../../doc/Nerve_GIC/nervevisu.jpg + :figclass: align-center + :alt: Visualization with KeplerMapper + + Visualization with KeplerMapper -- cgit v1.2.3