From f5c97bc9fd1c247045d35ddf261f9afe4d024406 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 20 Jul 2018 15:03:46 +0000 Subject: First try at interfacing the sparse rips in python. Needs at least documentation and tests. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3697 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 75bef59e90355853ee24807ca7453c4bb0a38f43 --- src/cython/cython/rips_complex.pyx | 50 +++++++++++++++++------------ src/cython/include/Rips_complex_interface.h | 39 ++++++++++++++-------- src/cython/test/test_rips_complex.py | 1 - 3 files changed, 55 insertions(+), 35 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index 59c16bff..620130ca 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -33,7 +33,11 @@ __license__ = "GPL v3" cdef extern from "Rips_complex_interface.h" namespace "Gudhi": cdef cppclass Rips_complex_interface "Gudhi::rips_complex::Rips_complex_interface": - Rips_complex_interface(vector[vector[double]] values, double threshold, bool euclidean) + Rips_complex_interface() + void init_points(vector[vector[double]] values, double threshold) + void init_matrix(vector[vector[double]] values, double threshold) + void init_points_sparse(vector[vector[double]] values, double threshold, double sparse) + void init_matrix_sparse(vector[vector[double]] values, double threshold, double sparse) void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max) # RipsComplex python interface @@ -44,14 +48,14 @@ cdef class RipsComplex: function, or a distance matrix. """ - cdef Rips_complex_interface * thisptr + cdef Rips_complex_interface thisref # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=None, distance_matrix=None, max_edge_length=float('inf')): + def __init__(self, points=None, distance_matrix=None, max_edge_length=float('inf'), sparse=None): """RipsComplex constructor. :param max_edge_length: Rips value. - :type max_edge_length: int + :type max_edge_length: float :param points: A list of points in d-Dimension. :type points: list of list of double @@ -61,27 +65,31 @@ cdef class RipsComplex: :param distance_matrix: A distance matrix (full square or lower triangular). :type points: list of list of double + + And in both cases + :param sparse: If this is not None, it switches to building a sparse Rips and represents the approximation parameter epsilon. + :type sparse: float """ # The real cython constructor - def __cinit__(self, points=None, distance_matrix=None, max_edge_length=float('inf')): - if distance_matrix is not None: - self.thisptr = new Rips_complex_interface(distance_matrix, max_edge_length, False) + def __cinit__(self, points=None, distance_matrix=None, max_edge_length=float('inf'), sparse=None): + if sparse is not None: + if distance_matrix is not None: + self.thisref.init_matrix_sparse(distance_matrix, max_edge_length, sparse) + else: + if points is None: + # Empty Rips construction + points=[] + self.thisref.init_points_sparse(points, max_edge_length, sparse) else: - if points is None: - # Empty Rips construction - points=[] - self.thisptr = new Rips_complex_interface(points, max_edge_length, True) - - - def __dealloc__(self): - if self.thisptr != NULL: - del self.thisptr + if distance_matrix is not None: + self.thisref.init_matrix(distance_matrix, max_edge_length) + else: + if points is None: + # Empty Rips construction + points=[] + self.thisref.init_points(points, max_edge_length) - def __is_defined(self): - """Returns true if RipsComplex pointer is not NULL. - """ - return self.thisptr != NULL def create_simplex_tree(self, max_dimension=1): """ @@ -92,5 +100,5 @@ cdef class RipsComplex: :rtype: SimplexTree """ simplex_tree = SimplexTree() - self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_dimension) + self.thisref.create_simplex_tree(simplex_tree.thisptr, max_dimension) return simplex_tree diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h index 8b6c9c35..f6fc79a1 100644 --- a/src/cython/include/Rips_complex_interface.h +++ b/src/cython/include/Rips_complex_interface.h @@ -25,8 +25,11 @@ #include #include +#include #include +#include + #include "Simplex_tree_interface.h" #include @@ -43,28 +46,38 @@ class Rips_complex_interface { using Distance_matrix = std::vector::Filtration_value>>; public: - Rips_complex_interface(const std::vector>& values, double threshold, bool euclidean) { - if (euclidean) { - // Rips construction where values is a vector of points - rips_complex_ = new Rips_complex::Filtration_value>(values, threshold, - Gudhi::Euclidean_distance()); - } else { - // Rips construction where values is a distance matrix - rips_complex_ = new Rips_complex::Filtration_value>(values, threshold); - } + void init_points(const std::vector>& points, double threshold) { + rips_complex_.emplace(points, threshold, Gudhi::Euclidean_distance()); + } + void init_matrix(const std::vector>& matrix, double threshold) { + rips_complex_.emplace(matrix, threshold); } - ~Rips_complex_interface() { - delete rips_complex_; + void init_points_sparse(const std::vector>& points, double threshold, double epsilon) { + sparse_rips_complex_.emplace(points, Gudhi::Euclidean_distance(), epsilon); + threshold_ = threshold; + } + void init_matrix_sparse(const std::vector>& matrix, double threshold, double epsilon) { + sparse_rips_complex_.emplace(matrix, epsilon); + threshold_ = threshold; } void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, int dim_max) { - rips_complex_->create_complex(*simplex_tree, dim_max); + if (rips_complex_) + rips_complex_->create_complex(*simplex_tree, dim_max); + else { + sparse_rips_complex_->create_complex(*simplex_tree, dim_max); + // This pruning should be done much earlier! It isn't that useful for sparse Rips, but it would be inconsistent not to do it. + simplex_tree->prune_above_filtration(threshold_); + } simplex_tree->initialize_filtration(); } private: - Rips_complex::Filtration_value>* rips_complex_; + // std::variant would work, but we don't require C++17 yet, and boost::variant is not super convenient. Anyway, storing a graph would make more sense. Or changing the interface completely so there is no such storage. + boost::optional::Filtration_value>> rips_complex_; + boost::optional::Filtration_value>> sparse_rips_complex_; + double threshold_; }; } // namespace rips_complex diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py index c37b5400..2eb1c61c 100755 --- a/src/cython/test/test_rips_complex.py +++ b/src/cython/test/test_rips_complex.py @@ -30,7 +30,6 @@ __license__ = "GPL v3" def test_empty_rips(): rips_complex = RipsComplex() - assert rips_complex.__is_defined() == True def test_rips_from_points(): point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] -- cgit v1.2.3 From d52036da23f887d56d13dd4f93c1049eb44301b1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 3 Aug 2018 09:41:38 +0000 Subject: plot persistence density functionnality with its documentation Fix some documentation issue in other graphiacl tools Add scipy as a dependency git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3736 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6481f1d6aa176bcf587f8875298a91cd22ac0319 --- src/cython/cython/persistence_graphical_tools.py | 74 +++++++++++++++++++++- src/cython/doc/persistence_graphical_tools_ref.rst | 1 + .../doc/persistence_graphical_tools_user.rst | 9 ++- src/cython/setup.py.in | 1 + 4 files changed, 80 insertions(+), 5 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 216ab8d6..7f604368 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -1,7 +1,9 @@ import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np +from scipy.stats import kde import os +import math """This file is part of the Gudhi Library. The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic C++ @@ -79,6 +81,8 @@ def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta). A reasonable value is between 0.05 and 0.5 - default is 0.1. :type inf_delta: float. + :param legend: Display the dimension color legend (default is False). + :type legend: boolean. :returns: A matplotlib object containing horizontal bar plot of persistence (launch `show()` method on it to display it). """ @@ -154,6 +158,8 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta). A reasonable value is between 0.05 and 0.5 - default is 0.1. :type inf_delta: float. + :param legend: Display the dimension color legend (default is False). + :type legend: boolean. :returns: A matplotlib object containing diagram plot of persistence (launch `show()` method on it to display it). """ @@ -174,7 +180,6 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] (min_birth, max_death) = __min_birth_max_death(persistence, band) - ind = 0 delta = ((max_death - min_birth) * inf_delta) # Replace infinity values with max_death + delta for diagram to be more # readable @@ -201,7 +206,6 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, # Infinite death case for diagram to be nicer plt.scatter(interval[1][0], infinity, alpha=alpha, color = palette[interval[0]]) - ind = ind + 1 if legend: dimensions = list(set(item[0] for item in persistence)) @@ -213,3 +217,69 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, # Ends plot on infinity value and starts a little bit before min_birth plt.axis([axis_start, infinity, axis_start, infinity + delta]) return plt + +def plot_persistence_density(persistence=[], persistence_file='', nbins=300, + max_plots=1000, cmap=plt.cm.hot_r, legend=False): + """This function plots the persistence density from persistence values list + or from a :doc:`persistence file `. Be aware that this + function does not distinguish the dimension, it is up to you to select the + required one. + + :param persistence: Persistence values list. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A :doc:`persistence file ` style name + (reset persistence if both are set). + :type persistence_file: string + :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins + over data extents (default is 300) + :type nbins: int. + :param max_plots: number of maximal plots to be displayed + Set it to 0 to see all, Default value is 1000. + (persistence will be sorted by life time if max_plots is set) + :type max_plots: int. + :param cmap: A matplotlib colormap (default is matplotlib.pyplot.cm.hot_r). + :type cmap: cf. matplotlib colormap. + :param legend: Display the color bar values (default is False). + :type legend: boolean. + :returns: A matplotlib object containing diagram plot of persistence + (launch `show()` method on it to display it). + """ + if persistence_file is not '': + if os.path.isfile(persistence_file): + # Reset persistence + persistence = [] + diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) + for key in diag.keys(): + for persistence_interval in diag[key]: + persistence.append((key, persistence_interval)) + else: + print("file " + persistence_file + " not found.") + return None + + if max_plots > 0 and max_plots < len(persistence): + # Sort by life time, then takes only the max_plots elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] + + # Set as numpy array birth and death (remove undefined values - inf and NaN) + birth = np.asarray([(interval[1][0]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + death = np.asarray([(interval[1][1]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + + # line display of equation : birth = death + x = np.linspace(death.min(), birth.max(), 1000) + plt.plot(x, x, color='k', linewidth=1.0) + + # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents + k = kde.gaussian_kde([birth,death]) + xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] + zi = k(np.vstack([xi.flatten(), yi.flatten()])) + + # Make the plot + plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap) + + if legend: + plt.colorbar() + + plt.title('Persistence density') + plt.xlabel('Birth') + plt.ylabel('Death') + return plt diff --git a/src/cython/doc/persistence_graphical_tools_ref.rst b/src/cython/doc/persistence_graphical_tools_ref.rst index a2c6bcef..54aff4bc 100644 --- a/src/cython/doc/persistence_graphical_tools_ref.rst +++ b/src/cython/doc/persistence_graphical_tools_ref.rst @@ -9,3 +9,4 @@ Persistence graphical tools reference manual .. autofunction:: gudhi.__min_birth_max_death .. autofunction:: gudhi.plot_persistence_barcode .. autofunction:: gudhi.plot_persistence_diagram +.. autofunction:: gudhi.plot_persistence_density diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index 292915eb..b21de06a 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -43,6 +43,9 @@ This function can display the persistence result as a diagram: legend=True) plt.show() +Persistence density +------------------- + If you want more information on a specific dimension, for instance: .. plot:: @@ -56,7 +59,7 @@ If you want more information on a specific dimension, for instance: gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file=\ persistence_file) dim = 1 - # Display all points with some transparency - plt = gudhi.plot_persistence_diagram([(dim,interval) for interval in diag[dim]], - max_plots=0, alpha=0.1) + # Display persistence density + plt = gudhi.plot_persistence_density([(dim,interval) for interval in diag[dim]], + max_plots=0, legend=True) plt.show() diff --git a/src/cython/setup.py.in b/src/cython/setup.py.in index ee381a1b..22b2954e 100644 --- a/src/cython/setup.py.in +++ b/src/cython/setup.py.in @@ -49,6 +49,7 @@ setup( install_requires = [ "matplotlib", "numpy", + "scipy", "cython", ], ) -- cgit v1.2.3 From feb6244de8f602e36fe101eb553ad5a6265665ee Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 3 Aug 2018 09:55:26 +0000 Subject: Add SciPy as a dependency in the installation process documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3737 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2d9d2c3f32ba3af5e9565f89e986ac437370b68e --- src/cython/doc/installation.rst | 9 ++++++++- src/cython/doc/persistence_graphical_tools_sum.inc | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst index 43ff85c5..ff6c7273 100644 --- a/src/cython/doc/installation.rst +++ b/src/cython/doc/installation.rst @@ -143,7 +143,7 @@ The following examples require the `Matplotlib `_: * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` -Numpy +NumPy ===== The :doc:`persistence graphical tools ` @@ -164,6 +164,13 @@ The following examples require the `NumPy `_: * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` +SciPy +===== + +The :doc:`persistence graphical tools ` +module requires `SciPy `_, a Python-based ecosystem of +open-source software for mathematics, science, and engineering. + Threading Building Blocks ========================= diff --git a/src/cython/doc/persistence_graphical_tools_sum.inc b/src/cython/doc/persistence_graphical_tools_sum.inc index d602daa7..c793a352 100644 --- a/src/cython/doc/persistence_graphical_tools_sum.inc +++ b/src/cython/doc/persistence_graphical_tools_sum.inc @@ -1,11 +1,11 @@ ================================================================= =================================== =================================== :Author: Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -:Requires: Matplotlib Numpy +:Requires: Matplotlib Numpy Scipy ================================================================= =================================== =================================== +-----------------------------------------------------------------+-----------------------------------------------------------------------+ | .. figure:: | These graphical tools comes on top of persistence results and allows | -| img/graphical_tools_representation.png | the user to build easily barcode and persistence diagram. | +| img/graphical_tools_representation.png | the user to build easily persistence barcode, diagram or density. | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------------+ | :doc:`persistence_graphical_tools_user` | :doc:`persistence_graphical_tools_ref` | -- cgit v1.2.3 From 2f10f837b791a1b002a18f1ba2b22de918eb54fe Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 16 Aug 2018 13:40:06 +0000 Subject: Code review : Try to import module. Functions are unavailable if not available. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3785 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 53c89a30f7992aa8d20e8330628c03291cea6473 --- .../modules/GUDHI_third_party_libraries.cmake | 1 + src/cython/CMakeLists.txt | 8 +- src/cython/cython/persistence_graphical_tools.py | 202 +++++++++++---------- 3 files changed, 108 insertions(+), 103 deletions(-) (limited to 'src/cython') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index f03c2177..1ad0c1fd 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -143,6 +143,7 @@ if( PYTHONINTERP_FOUND ) find_python_module("pytest") find_python_module("matplotlib") find_python_module("numpy") + find_python_module("scipy") endif() if(NOT GUDHI_CYTHON_PATH) diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 1849a6ec..542be9b0 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -54,10 +54,8 @@ if(CYTHON_FOUND) if(NUMPY_FOUND) add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") endif() - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") + if(SCIPY_FOUND) + add_gudhi_debug_info("Scipy version ${SCIPY_VERSION}") endif() message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_VERSION} - Sphinx is ${SPHINX_PATH}") @@ -368,7 +366,7 @@ if(CYTHON_FOUND) add_gudhi_py_test(test_reader_utils) # Documentation generation is available through sphinx - requires all modules - if(SPHINX_PATH AND MATPLOTLIB_FOUND AND NUMPY_FOUND AND NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + if(SPHINX_PATH AND MATPLOTLIB_FOUND AND NUMPY_FOUND AND SCIPY_FOUND AND NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") # User warning - Sphinx is a static pages generator, and configured to work fine with user_version # Images and biblio warnings because not found on developper version diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index e172c65b..e154c0b2 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -24,44 +24,42 @@ __author__ = "Vincent Rouvreau, Bertrand Michel" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" +def __min_birth_max_death(persistence, band=0.): + """This function returns (min_birth, max_death) from the persistence. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param band: band + :type band: float. + :returns: (float, float) -- (min_birth, max_death). + """ + # Look for minimum birth date and maximum death date for plot optimisation + max_death = 0 + min_birth = persistence[0][1][0] + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + if float(interval[1][1]) > max_death: + max_death = float(interval[1][1]) + if float(interval[1][0]) > max_death: + max_death = float(interval[1][0]) + if float(interval[1][0]) < min_birth: + min_birth = float(interval[1][0]) + if band > 0.: + max_death += band + return (min_birth, max_death) + +""" +Only 13 colors for the palette +""" +palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', + '#000000', '#880000', '#008800', '#000088', '#888800', '#880088', + '#008888'] + try: import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np - from scipy.stats import kde import os - import math - - def __min_birth_max_death(persistence, band=0.): - """This function returns (min_birth, max_death) from the persistence. - - :param persistence: The persistence to plot. - :type persistence: list of tuples(dimension, tuple(birth, death)). - :param band: band - :type band: float. - :returns: (float, float) -- (min_birth, max_death). - """ - # Look for minimum birth date and maximum death date for plot optimisation - max_death = 0 - min_birth = persistence[0][1][0] - for interval in reversed(persistence): - if float(interval[1][1]) != float('inf'): - if float(interval[1][1]) > max_death: - max_death = float(interval[1][1]) - if float(interval[1][0]) > max_death: - max_death = float(interval[1][0]) - if float(interval[1][0]) < min_birth: - min_birth = float(interval[1][0]) - if band > 0.: - max_death += band - return (min_birth, max_death) - - """ - Only 13 colors for the palette - """ - palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', - '#000000', '#880000', '#008800', '#000088', '#888800', '#880088', - '#008888'] def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, max_barcodes=1000, inf_delta=0.1, legend=False): @@ -220,71 +218,79 @@ try: plt.axis([axis_start, infinity, axis_start, infinity + delta]) return plt - def plot_persistence_density(persistence=[], persistence_file='', nbins=300, - max_plots=1000, cmap=plt.cm.hot_r, legend=False): - """This function plots the persistence density from persistence values list - or from a :doc:`persistence file `. Be aware that this - function does not distinguish the dimension, it is up to you to select the - required one. - - :param persistence: Persistence values list. - :type persistence: list of tuples(dimension, tuple(birth, death)). - :param persistence_file: A :doc:`persistence file ` style name - (reset persistence if both are set). - :type persistence_file: string - :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins - over data extents (default is 300) - :type nbins: int. - :param max_plots: number of maximal plots to be displayed - Set it to 0 to see all, Default value is 1000. - (persistence will be sorted by life time if max_plots is set) - :type max_plots: int. - :param cmap: A matplotlib colormap (default is matplotlib.pyplot.cm.hot_r). - :type cmap: cf. matplotlib colormap. - :param legend: Display the color bar values (default is False). - :type legend: boolean. - :returns: A matplotlib object containing diagram plot of persistence - (launch `show()` method on it to display it). - """ - if persistence_file is not '': - if os.path.isfile(persistence_file): - # Reset persistence - persistence = [] - diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) - for key in diag.keys(): - for persistence_interval in diag[key]: - persistence.append((key, persistence_interval)) - else: - print("file " + persistence_file + " not found.") - return None - - if max_plots > 0 and max_plots < len(persistence): - # Sort by life time, then takes only the max_plots elements - persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] - - # Set as numpy array birth and death (remove undefined values - inf and NaN) - birth = np.asarray([(interval[1][0]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) - death = np.asarray([(interval[1][1]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) - - # line display of equation : birth = death - x = np.linspace(death.min(), birth.max(), 1000) - plt.plot(x, x, color='k', linewidth=1.0) - - # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents - k = kde.gaussian_kde([birth,death]) - xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] - zi = k(np.vstack([xi.flatten(), yi.flatten()])) - - # Make the plot - plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap) - - if legend: - plt.colorbar() - - plt.title('Persistence density') - plt.xlabel('Birth') - plt.ylabel('Death') - return plt + try: + from scipy.stats import kde + import math + + def plot_persistence_density(persistence=[], persistence_file='', nbins=300, + max_plots=1000, cmap=plt.cm.hot_r, legend=False): + """This function plots the persistence density from persistence values list + or from a :doc:`persistence file `. Be aware that this + function does not distinguish the dimension, it is up to you to select the + required one. + + :param persistence: Persistence values list. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A :doc:`persistence file ` style name + (reset persistence if both are set). + :type persistence_file: string + :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins + over data extents (default is 300) + :type nbins: int. + :param max_plots: number of maximal plots to be displayed + Set it to 0 to see all, Default value is 1000. + (persistence will be sorted by life time if max_plots is set) + :type max_plots: int. + :param cmap: A matplotlib colormap (default is matplotlib.pyplot.cm.hot_r). + :type cmap: cf. matplotlib colormap. + :param legend: Display the color bar values (default is False). + :type legend: boolean. + :returns: A matplotlib object containing diagram plot of persistence + (launch `show()` method on it to display it). + """ + if persistence_file is not '': + if os.path.isfile(persistence_file): + # Reset persistence + persistence = [] + diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) + for key in diag.keys(): + for persistence_interval in diag[key]: + persistence.append((key, persistence_interval)) + else: + print("file " + persistence_file + " not found.") + return None + + if max_plots > 0 and max_plots < len(persistence): + # Sort by life time, then takes only the max_plots elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] + + # Set as numpy array birth and death (remove undefined values - inf and NaN) + birth = np.asarray([(interval[1][0]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + death = np.asarray([(interval[1][1]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + + # line display of equation : birth = death + x = np.linspace(death.min(), birth.max(), 1000) + plt.plot(x, x, color='k', linewidth=1.0) + + # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents + k = kde.gaussian_kde([birth,death]) + xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] + zi = k(np.vstack([xi.flatten(), yi.flatten()])) + + # Make the plot + plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap) + + if legend: + plt.colorbar() + + plt.title('Persistence density') + plt.xlabel('Birth') + plt.ylabel('Death') + return plt + + except ImportError: + # Continue in case of import error, functions won't be available + pass except ImportError: # Continue in case of import error, functions won't be available -- cgit v1.2.3 From efab7ccf5850ccc58018b7f856d209c4094e67c5 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 16 Aug 2018 14:35:08 +0000 Subject: Bug fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3788 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d8b898ca963d8d956307bb1dfd8abea1acbe6c96 --- src/cython/cython/persistence_graphical_tools.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index e154c0b2..14c4cf3f 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -205,7 +205,6 @@ try: # Infinite death case for diagram to be nicer plt.scatter(interval[1][0], infinity, alpha=alpha, color = palette[interval[0]]) - ind = ind + 1 if legend: dimensions = list(set(item[0] for item in persistence)) -- cgit v1.2.3 From b7354cd2ab0b265787348866da5d08cce15aee66 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 09:38:55 +0000 Subject: Code review : add a parameter to select dimension for plot_persistence_density. Default is None and mix all dimensions git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3794 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 493f5ecfad2bcf0ee4a40ec7b315863c471d088f --- src/cython/cython/persistence_graphical_tools.py | 43 +++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 14c4cf3f..949f5c37 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -221,26 +221,31 @@ try: from scipy.stats import kde import math - def plot_persistence_density(persistence=[], persistence_file='', nbins=300, - max_plots=1000, cmap=plt.cm.hot_r, legend=False): - """This function plots the persistence density from persistence values list - or from a :doc:`persistence file `. Be aware that this - function does not distinguish the dimension, it is up to you to select the - required one. + def plot_persistence_density(persistence=[], persistence_file='', + nbins=300, max_plots=1000, dimension=None, + cmap=plt.cm.hot_r, legend=False): + """This function plots the persistence density from persistence + values list or from a :doc:`persistence file `. Be + aware that this function does not distinguish the dimension, it is + up to you to select the required one. :param persistence: Persistence values list. :type persistence: list of tuples(dimension, tuple(birth, death)). - :param persistence_file: A :doc:`persistence file ` style name - (reset persistence if both are set). + :param persistence_file: A :doc:`persistence file ` + style name (reset persistence if both are set). :type persistence_file: string - :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins - over data extents (default is 300) + :param nbins: Evaluate a gaussian kde on a regular grid of nbins x + nbins over data extents (default is 300) :type nbins: int. :param max_plots: number of maximal plots to be displayed Set it to 0 to see all, Default value is 1000. (persistence will be sorted by life time if max_plots is set) :type max_plots: int. - :param cmap: A matplotlib colormap (default is matplotlib.pyplot.cm.hot_r). + :param dimension: the dimension to be selected in the intervals + (default is None to mix all dimensions). + :type dimension: int. + :param cmap: A matplotlib colormap (default is + matplotlib.pyplot.cm.hot_r). :type cmap: cf. matplotlib colormap. :param legend: Display the color bar values (default is False). :type legend: boolean. @@ -259,13 +264,21 @@ try: print("file " + persistence_file + " not found.") return None - if max_plots > 0 and max_plots < len(persistence): + persistence_dim = [] + if dimension is not None: + persistence_dim = [(dim_interval) for dim_interval in persistence if (dim_interval[0] == dimension)] + else: + persistence_dim = persistence + + if max_plots > 0 and max_plots < len(persistence_dim): # Sort by life time, then takes only the max_plots elements - persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] + persistence_dim = sorted(persistence_dim, + key=lambda life_time: life_time[1][1]-life_time[1][0], + reverse=True)[:max_plots] # Set as numpy array birth and death (remove undefined values - inf and NaN) - birth = np.asarray([(interval[1][0]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) - death = np.asarray([(interval[1][1]) for interval in persistence if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + birth = np.asarray([(interval[1][0]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + death = np.asarray([(interval[1][1]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) # line display of equation : birth = death x = np.linspace(death.min(), birth.max(), 1000) -- cgit v1.2.3 From 1865751c055ad01ba159a13d22e42204195c2ccb Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 09:50:15 +0000 Subject: Doc review : rephrase max_plots explanation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3795 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f6059d3a242eed53dfdddb76ffed33f99892f4bc --- src/cython/cython/persistence_graphical_tools.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 949f5c37..0b3357f8 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -138,21 +138,22 @@ try: def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, band=0., max_plots=1000, inf_delta=0.1, legend=False): - """This function plots the persistence diagram from persistence values list - or from a :doc:`persistence file `. + """This function plots the persistence diagram from persistence values + list or from a :doc:`persistence file `. :param persistence: Persistence values list. :type persistence: list of tuples(dimension, tuple(birth, death)). :param persistence_file: A :doc:`persistence file ` style name (reset persistence if both are set). :type persistence_file: string - :param alpha: plot transparency value (0.0 transparent through 1.0 opaque - default is 0.6). + :param alpha: plot transparency value (0.0 transparent through 1.0 + opaque - default is 0.6). :type alpha: float. :param band: band (not displayed if :math:`\leq` 0. - default is 0.) :type band: float. - :param max_plots: number of maximal plots to be displayed - Set it to 0 to see all, Default value is 1000. - (persistence will be sorted by life time if max_plots is set) + :param max_plots: maximal number of points to display. Selected points + are those with the longest life time. Set it to 0 to see all, + default value is 1000. :type max_plots: int. :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta). A reasonable value is between 0.05 and 0.5 - default is 0.1. @@ -237,9 +238,9 @@ try: :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents (default is 300) :type nbins: int. - :param max_plots: number of maximal plots to be displayed - Set it to 0 to see all, Default value is 1000. - (persistence will be sorted by life time if max_plots is set) + :param max_plots: maximal number of points to display. Selected points + are those with the longest life time. Set it to 0 to see all, + default value is 1000. :type max_plots: int. :param dimension: the dimension to be selected in the intervals (default is None to mix all dimensions). -- cgit v1.2.3 From 67ae5aa70e70097f72f868ebba1fa8e7ff96297d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 12:41:10 +0000 Subject: doc review : modification of persistence barcode example to make it more relevant git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3796 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 17acc09cdf7d09b13c177334efb1e309c4fd8d9c --- .../doc/persistence_graphical_tools_user.rst | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index b21de06a..0047f9c8 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -19,12 +19,15 @@ This function can display the persistence result as a barcode: import gudhi - perseus_file = gudhi.__root_source_dir__ + '/data/bitmap/3d_torus.txt' - periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file=perseus_file) - diag = periodic_cc.persistence() - print("diag = ", diag) - plt = gudhi.plot_persistence_barcode(diag) - plt.show() + off_file = gudhi.__root_source_dir__ + '/data/points/tore3D_300.off' + point_cloud = gudhi.read_off(off_file=off_file) + + rips_complex = gudhi.RipsComplex(points=point_cloud, max_edge_length=0.7) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) + diag = simplex_tree.persistence(min_persistence=0.4) + + plot = gudhi.plot_persistence_barcode(diag) + plot.show() Show persistence as a diagram ----------------------------- @@ -53,13 +56,9 @@ If you want more information on a specific dimension, for instance: import gudhi + # rips_on_tore3D_1307.pers obtained from write_persistence_diagram method persistence_file=gudhi.__root_source_dir__ + \ '/data/persistence_diagram/rips_on_tore3D_1307.pers' - diag = \ - gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file=\ - persistence_file) - dim = 1 - # Display persistence density - plt = gudhi.plot_persistence_density([(dim,interval) for interval in diag[dim]], - max_plots=0, legend=True) + plt = gudhi.plot_persistence_density(persistence_file=persistence_file, + max_plots=0, dimension=1, legend=True) plt.show() -- cgit v1.2.3 From a5464d68d2848d21fc777809ab686b1bbf4e0139 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 13:32:41 +0000 Subject: Code review : Add a bw_method parameter to plot_persistence_density for the standard deviation of the Gaussian git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3799 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3bbc988434951bb429acd44b1f31f8310bb9ba9c --- src/cython/cython/persistence_graphical_tools.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 0b3357f8..026e365d 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -223,7 +223,8 @@ try: import math def plot_persistence_density(persistence=[], persistence_file='', - nbins=300, max_plots=1000, dimension=None, + nbins=300, bw_method=None, + max_plots=1000, dimension=None, cmap=plt.cm.hot_r, legend=False): """This function plots the persistence density from persistence values list or from a :doc:`persistence file `. Be @@ -238,6 +239,14 @@ try: :param nbins: Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents (default is 300) :type nbins: int. + :param bw_method: The method used to calculate the estimator + bandwidth. This can be 'scott', 'silverman', a scalar constant + or a callable. If a scalar, this will be used directly as + kde.factor. If a callable, it should take a gaussian_kde + instance as only parameter and return a scalar. If None + (default), 'scott' is used. See scipy.stats.gaussian_kde + documentation for more details. + :type bw_method: str, scalar or callable, optional. :param max_plots: maximal number of points to display. Selected points are those with the longest life time. Set it to 0 to see all, default value is 1000. @@ -286,7 +295,7 @@ try: plt.plot(x, x, color='k', linewidth=1.0) # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents - k = kde.gaussian_kde([birth,death]) + k = kde.gaussian_kde([birth,death], bw_method=bw_method) xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] zi = k(np.vstack([xi.flatten(), yi.flatten()])) -- cgit v1.2.3 From 24c661e98b8f8e0f2c492fcf63e68615dbd9ae84 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 13:45:08 +0000 Subject: Doc review : inf_delta explanation improvement git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3800 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 01fff74d79228431d77a46b713ac656ab7e84dc0 --- src/cython/cython/persistence_graphical_tools.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 026e365d..4c8467bd 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -71,14 +71,16 @@ try: :param persistence_file: A :doc:`persistence file ` style name (reset persistence if both are set). :type persistence_file: string - :param alpha: barcode transparency value (0.0 transparent through 1.0 opaque - default is 0.6). + :param alpha: barcode transparency value (0.0 transparent through 1.0 + opaque - default is 0.6). :type alpha: float. :param max_barcodes: number of maximal barcodes to be displayed. Set it to 0 to see all, Default value is 1000. (persistence will be sorted by life time if max_barcodes is set) :type max_barcodes: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta). - A reasonable value is between 0.05 and 0.5 - default is 0.1. + :param inf_delta: Infinity is placed at ((max_death - min_birth) x + inf_delta) above the highest point. A reasonable value is between + 0.05 and 0.5 - default is 0.1. :type inf_delta: float. :param legend: Display the dimension color legend (default is False). :type legend: boolean. @@ -155,8 +157,9 @@ try: are those with the longest life time. Set it to 0 to see all, default value is 1000. :type max_plots: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta). - A reasonable value is between 0.05 and 0.5 - default is 0.1. + :param inf_delta: Infinity is placed at ((max_death - min_birth) x + inf_delta) above the highest point. A reasonable value is between + 0.05 and 0.5 - default is 0.1. :type inf_delta: float. :param legend: Display the dimension color legend (default is False). :type legend: boolean. -- cgit v1.2.3 From 7e1d78ec22e0e53bbf4a36aaea1b77fa48f5d40d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 13:58:46 +0000 Subject: Code review : Rename max_plots with max_intervals for persistence density git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3801 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8d20ee2f721b856bba69bc5bc10db26032649129 --- src/cython/cython/persistence_graphical_tools.py | 14 +++++++------- src/cython/doc/persistence_graphical_tools_user.rst | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 4c8467bd..96b579bd 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -250,10 +250,10 @@ try: (default), 'scott' is used. See scipy.stats.gaussian_kde documentation for more details. :type bw_method: str, scalar or callable, optional. - :param max_plots: maximal number of points to display. Selected points - are those with the longest life time. Set it to 0 to see all, - default value is 1000. - :type max_plots: int. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. :param dimension: the dimension to be selected in the intervals (default is None to mix all dimensions). :type dimension: int. @@ -283,11 +283,11 @@ try: else: persistence_dim = persistence - if max_plots > 0 and max_plots < len(persistence_dim): - # Sort by life time, then takes only the max_plots elements + if max_intervals > 0 and max_intervals < len(persistence_dim): + # Sort by life time, then takes only the max_intervals elements persistence_dim = sorted(persistence_dim, key=lambda life_time: life_time[1][1]-life_time[1][0], - reverse=True)[:max_plots] + reverse=True)[:max_intervals] # Set as numpy array birth and death (remove undefined values - inf and NaN) birth = np.asarray([(interval[1][0]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index 0047f9c8..fda086c3 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -60,5 +60,5 @@ If you want more information on a specific dimension, for instance: persistence_file=gudhi.__root_source_dir__ + \ '/data/persistence_diagram/rips_on_tore3D_1307.pers' plt = gudhi.plot_persistence_density(persistence_file=persistence_file, - max_plots=0, dimension=1, legend=True) + max_intervals=0, dimension=1, legend=True) plt.show() -- cgit v1.2.3 From 6ebc098c9bbf233b5a4325faec04236feedab191 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 14:48:08 +0000 Subject: Code review : rename max_plots and max_barcodes as max_intervals for peristence_graphical_tools git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3803 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ad73f7e6cc6d72c3ba24b5ac947265c78a29f387 --- src/cython/cython/persistence_graphical_tools.py | 43 ++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 96b579bd..85d2a5ad 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -62,7 +62,8 @@ try: import os def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, - max_barcodes=1000, inf_delta=0.1, legend=False): + max_intervals=1000, max_barcodes=1000, + inf_delta=0.1, legend=False): """This function plots the persistence bar code from persistence values list or from a :doc:`persistence file `. @@ -74,10 +75,10 @@ try: :param alpha: barcode transparency value (0.0 transparent through 1.0 opaque - default is 0.6). :type alpha: float. - :param max_barcodes: number of maximal barcodes to be displayed. - Set it to 0 to see all, Default value is 1000. - (persistence will be sorted by life time if max_barcodes is set) - :type max_barcodes: int. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta) above the highest point. A reasonable value is between 0.05 and 0.5 - default is 0.1. @@ -99,9 +100,13 @@ try: print("file " + persistence_file + " not found.") return None - if max_barcodes > 0 and max_barcodes < len(persistence): - # Sort by life time, then takes only the max_plots elements - persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_barcodes] + if max_barcodes is not 1000: + print('Deprecated parameter. It has been replaced by max_intervals') + max_intervals = max_barcodes + + if max_intervals > 0 and max_intervals < len(persistence): + # Sort by life time, then takes only the max_intervals elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_intervals] persistence = sorted(persistence, key=lambda birth: birth[1][0]) @@ -139,7 +144,7 @@ try: return plt def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, - band=0., max_plots=1000, inf_delta=0.1, legend=False): + band=0., max_intervals=1000, max_plots=1000, inf_delta=0.1, legend=False): """This function plots the persistence diagram from persistence values list or from a :doc:`persistence file `. @@ -153,10 +158,10 @@ try: :type alpha: float. :param band: band (not displayed if :math:`\leq` 0. - default is 0.) :type band: float. - :param max_plots: maximal number of points to display. Selected points - are those with the longest life time. Set it to 0 to see all, - default value is 1000. - :type max_plots: int. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta) above the highest point. A reasonable value is between 0.05 and 0.5 - default is 0.1. @@ -178,9 +183,13 @@ try: print("file " + persistence_file + " not found.") return None - if max_plots > 0 and max_plots < len(persistence): - # Sort by life time, then takes only the max_plots elements - persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] + if max_plots is not 1000: + print('Deprecated parameter. It has been replaced by max_intervals') + max_intervals = max_plots + + if max_intervals > 0 and max_intervals < len(persistence): + # Sort by life time, then takes only the max_intervals elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_intervals] (min_birth, max_death) = __min_birth_max_death(persistence, band) delta = ((max_death - min_birth) * inf_delta) @@ -227,7 +236,7 @@ try: def plot_persistence_density(persistence=[], persistence_file='', nbins=300, bw_method=None, - max_plots=1000, dimension=None, + max_intervals=1000, dimension=None, cmap=plt.cm.hot_r, legend=False): """This function plots the persistence density from persistence values list or from a :doc:`persistence file `. Be -- cgit v1.2.3 From b301bf80daaac521f16d43120a8a30a2af9eb515 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 17 Aug 2018 15:29:19 +0000 Subject: Makes clearer dependencies for each function of persistence graphical tools git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3804 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7572f54368ff235f5e78df74121bf6b1ee107177 --- src/cython/doc/persistence_graphical_tools_sum.inc | 2 +- src/cython/doc/persistence_graphical_tools_user.rst | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/persistence_graphical_tools_sum.inc b/src/cython/doc/persistence_graphical_tools_sum.inc index c793a352..5577cf99 100644 --- a/src/cython/doc/persistence_graphical_tools_sum.inc +++ b/src/cython/doc/persistence_graphical_tools_sum.inc @@ -1,6 +1,6 @@ ================================================================= =================================== =================================== :Author: Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -:Requires: Matplotlib Numpy Scipy +:Requires: matplotlib numpy scipy ================================================================= =================================== =================================== +-----------------------------------------------------------------+-----------------------------------------------------------------------+ diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index fda086c3..b2124fdd 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -12,6 +12,9 @@ Definition Show persistence as a barcode ----------------------------- +.. note:: + this function requires matplotlib and numpy to be available + This function can display the persistence result as a barcode: .. plot:: @@ -32,6 +35,9 @@ This function can display the persistence result as a barcode: Show persistence as a diagram ----------------------------- +.. note:: + this function requires matplotlib and numpy to be available + This function can display the persistence result as a diagram: .. plot:: @@ -49,6 +55,9 @@ This function can display the persistence result as a diagram: Persistence density ------------------- +.. note:: + this function requires matplotlib, numpy and scipy to be available + If you want more information on a specific dimension, for instance: .. plot:: -- cgit v1.2.3 From 30554aab477f1a189f7270326b706f09e681e24a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 09:24:41 +0000 Subject: Add debug traces git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3851 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 00f56b397048aca87422e6da9385b2622acf1094 --- src/cython/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 1849a6ec..97a99e59 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -1,7 +1,9 @@ project(Cython) function( add_gudhi_cython_lib THE_LIB ) + message("##### add_gudhi_cython_lib on ${THE_LIB}") if(EXISTS ${THE_LIB}) + message("##### EXISTS") get_filename_component(THE_LIB_FILE_NAME ${THE_LIB} NAME_WE) if(WIN32) message("++ ${THE_LIB} => THE_LIB_FILE_NAME = ${THE_LIB_FILE_NAME}") -- cgit v1.2.3 From 16c796735dafe95e4c93d80a0785f2a0a8e0e1cd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 09:34:26 +0000 Subject: Add debug traces git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3852 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1a99305e1bfab4d86f5a10371dbad3438f3b0580 --- src/cython/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 97a99e59..37e3de79 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -132,6 +132,7 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) + message("##### add_gudhi_cython_lib on ${Boost_THREAD_LIBRARY}") add_gudhi_cython_lib(${Boost_THREAD_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() @@ -141,6 +142,7 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") + message("##### add_gudhi_cython_lib on ${CGAL_LIBRARY}") add_gudhi_cython_lib(${CGAL_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, -- cgit v1.2.3 From 8d3550092122a71b70bd310d5fd9e9976bc0b9dd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 11:07:09 +0000 Subject: Add debug traces git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3853 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e8792fc3427cb4f4e92f3297aa3f4aea57c54e60 --- src/cython/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 37e3de79..41230a69 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -132,7 +132,7 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - message("##### add_gudhi_cython_lib on ${Boost_THREAD_LIBRARY}") + message("##### add_gudhi_cython_lib Boost_THREAD_LIBRARY - ${Boost_THREAD_LIBRARY}") add_gudhi_cython_lib(${Boost_THREAD_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() @@ -142,10 +142,11 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - message("##### add_gudhi_cython_lib on ${CGAL_LIBRARY}") + message("##### add_gudhi_cython_lib CGAL_LIBRARY - ${CGAL_LIBRARY}") add_gudhi_cython_lib(${CGAL_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, + message("##### add_gudhi_cython_lib Boost_SYSTEM_LIBRARY - ${Boost_SYSTEM_LIBRARY}") add_gudhi_cython_lib(${Boost_SYSTEM_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif(CGAL_HEADER_ONLY) @@ -153,6 +154,7 @@ if(CYTHON_FOUND) if(GMP_FOUND) add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") + message("##### add_gudhi_cython_lib GMP_LIBRARIES - ${GMP_LIBRARIES}") add_gudhi_cython_lib(${GMP_LIBRARIES}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") if(GMPXX_FOUND) -- cgit v1.2.3 From 6048f92357bbce6de009c2441d9354e5f2f4b8ae Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 11:16:58 +0000 Subject: Add CGAL_LIBRARIES git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3854 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0b8ee8cf61dca1b74481d556615e55caa39246ae --- src/cython/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 41230a69..50355f84 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -142,6 +142,8 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") + message("##### add_gudhi_cython_lib CGAL_LIBRARIES - ${CGAL_LIBRARIES}") + add_gudhi_cython_lib(${CGAL_LIBRARIES}) message("##### add_gudhi_cython_lib CGAL_LIBRARY - ${CGAL_LIBRARY}") add_gudhi_cython_lib(${CGAL_LIBRARY}) set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") -- cgit v1.2.3 From fd7e0464bde1a357fda43ced4ff26b36bdc58a56 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 11:23:50 +0000 Subject: Pass parameters to cmake function through double quote for unset variables case git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3855 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 57ff4e884e6575cc7938da3937a7a0090567ad74 --- src/cython/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 50355f84..f9eccaa3 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -133,7 +133,7 @@ if(CYTHON_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) message("##### add_gudhi_cython_lib Boost_THREAD_LIBRARY - ${Boost_THREAD_LIBRARY}") - add_gudhi_cython_lib(${Boost_THREAD_LIBRARY}) + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() # Add CGAL compilation args @@ -143,13 +143,13 @@ if(CYTHON_FOUND) else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") message("##### add_gudhi_cython_lib CGAL_LIBRARIES - ${CGAL_LIBRARIES}") - add_gudhi_cython_lib(${CGAL_LIBRARIES}) + add_gudhi_cython_lib("${CGAL_LIBRARIES}") message("##### add_gudhi_cython_lib CGAL_LIBRARY - ${CGAL_LIBRARY}") - add_gudhi_cython_lib(${CGAL_LIBRARY}) + add_gudhi_cython_lib("${CGAL_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, message("##### add_gudhi_cython_lib Boost_SYSTEM_LIBRARY - ${Boost_SYSTEM_LIBRARY}") - add_gudhi_cython_lib(${Boost_SYSTEM_LIBRARY}) + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif(CGAL_HEADER_ONLY) # GMP and GMPXX are not required, but if present, CGAL will link with them. @@ -157,12 +157,12 @@ if(CYTHON_FOUND) add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") message("##### add_gudhi_cython_lib GMP_LIBRARIES - ${GMP_LIBRARIES}") - add_gudhi_cython_lib(${GMP_LIBRARIES}) + add_gudhi_cython_lib("${GMP_LIBRARIES}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") if(GMPXX_FOUND) add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") - add_gudhi_cython_lib(${GMPXX_LIBRARIES}) + add_gudhi_cython_lib("${GMPXX_LIBRARIES}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") endif(GMPXX_FOUND) endif(GMP_FOUND) @@ -184,8 +184,8 @@ if(CYTHON_FOUND) if (TBB_FOUND AND WITH_GUDHI_USE_TBB) add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") - add_gudhi_cython_lib(${TBB_RELEASE_LIBRARY}) - add_gudhi_cython_lib(${TBB_MALLOC_RELEASE_LIBRARY}) + add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}") + add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ") set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") endif() -- cgit v1.2.3 From 2ffe7a5477803025b3de2abf59725d8dc2588f73 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 11:38:56 +0000 Subject: Try with boost release and debug lib versions git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3856 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 130a4319577ef0ec8c10a87c98b7ffcf6f16d808 --- src/cython/CMakeLists.txt | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index f9eccaa3..fb613639 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -132,8 +132,14 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - message("##### add_gudhi_cython_lib Boost_THREAD_LIBRARY - ${Boost_THREAD_LIBRARY}") - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY}") + message("##### Boost_THREAD_LIBRARY - ${Boost_THREAD_LIBRARY}") + if(CMAKE_BUILD_TYPE MATCHES Debug) + message("##### Boost_THREAD_LIBRARY_DEBUG - ${Boost_THREAD_LIBRARY_DEBUG}") + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") + else() + message("##### Boost_THREAD_LIBRARY_RELEASE - ${Boost_THREAD_LIBRARY_RELEASE}") + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") + endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() # Add CGAL compilation args @@ -142,14 +148,20 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - message("##### add_gudhi_cython_lib CGAL_LIBRARIES - ${CGAL_LIBRARIES}") + message("##### CGAL_LIBRARIES - ${CGAL_LIBRARIES}") add_gudhi_cython_lib("${CGAL_LIBRARIES}") - message("##### add_gudhi_cython_lib CGAL_LIBRARY - ${CGAL_LIBRARY}") + message("##### CGAL_LIBRARY - ${CGAL_LIBRARY}") add_gudhi_cython_lib("${CGAL_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, - message("##### add_gudhi_cython_lib Boost_SYSTEM_LIBRARY - ${Boost_SYSTEM_LIBRARY}") - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY}") + message("##### Boost_SYSTEM_LIBRARY - ${Boost_SYSTEM_LIBRARY}") + if(CMAKE_BUILD_TYPE MATCHES Debug) + message("##### Boost_SYSTEM_LIBRARY_DEBUG - ${Boost_SYSTEM_LIBRARY_DEBUG}") + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") + else() + message("##### Boost_SYSTEM_LIBRARY_RELEASE - ${Boost_SYSTEM_LIBRARY_RELEASE}") + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif(CGAL_HEADER_ONLY) # GMP and GMPXX are not required, but if present, CGAL will link with them. -- cgit v1.2.3 From c5b865f6e9e1ae60de2720c76aee1dfccf470023 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 11:59:31 +0000 Subject: Works fine in debug and release mode git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/windows_cgal_non_header_only_compilation_issue@3857 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2cc11e2a6e7f8eed6c234c17cad7ff04efdbc659 --- src/cython/CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index fb613639..90a2fcf7 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -1,9 +1,7 @@ project(Cython) function( add_gudhi_cython_lib THE_LIB ) - message("##### add_gudhi_cython_lib on ${THE_LIB}") if(EXISTS ${THE_LIB}) - message("##### EXISTS") get_filename_component(THE_LIB_FILE_NAME ${THE_LIB} NAME_WE) if(WIN32) message("++ ${THE_LIB} => THE_LIB_FILE_NAME = ${THE_LIB_FILE_NAME}") @@ -132,12 +130,9 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - message("##### Boost_THREAD_LIBRARY - ${Boost_THREAD_LIBRARY}") if(CMAKE_BUILD_TYPE MATCHES Debug) - message("##### Boost_THREAD_LIBRARY_DEBUG - ${Boost_THREAD_LIBRARY_DEBUG}") add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") else() - message("##### Boost_THREAD_LIBRARY_RELEASE - ${Boost_THREAD_LIBRARY_RELEASE}") add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") @@ -148,18 +143,13 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - message("##### CGAL_LIBRARIES - ${CGAL_LIBRARIES}") add_gudhi_cython_lib("${CGAL_LIBRARIES}") - message("##### CGAL_LIBRARY - ${CGAL_LIBRARY}") add_gudhi_cython_lib("${CGAL_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, - message("##### Boost_SYSTEM_LIBRARY - ${Boost_SYSTEM_LIBRARY}") if(CMAKE_BUILD_TYPE MATCHES Debug) - message("##### Boost_SYSTEM_LIBRARY_DEBUG - ${Boost_SYSTEM_LIBRARY_DEBUG}") add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") else() - message("##### Boost_SYSTEM_LIBRARY_RELEASE - ${Boost_SYSTEM_LIBRARY_RELEASE}") add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") @@ -168,7 +158,6 @@ if(CYTHON_FOUND) if(GMP_FOUND) add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") - message("##### add_gudhi_cython_lib GMP_LIBRARIES - ${GMP_LIBRARIES}") add_gudhi_cython_lib("${GMP_LIBRARIES}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") if(GMPXX_FOUND) -- cgit v1.2.3 From ec9100908202bb5b7a6ba835edeabf3272d70e98 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 31 Aug 2018 12:38:13 +0000 Subject: Link with release third parties library version, even in debug mode git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3863 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e33e15081b3029d9dfd4edc464d91b0db47e1754 --- src/cython/CMakeLists.txt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 90a2fcf7..cf57d872 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -130,11 +130,7 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - if(CMAKE_BUILD_TYPE MATCHES Debug) - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") - else() - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") - endif() + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() # Add CGAL compilation args @@ -143,15 +139,10 @@ if(CYTHON_FOUND) set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") else(CGAL_HEADER_ONLY) add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - add_gudhi_cython_lib("${CGAL_LIBRARIES}") add_gudhi_cython_lib("${CGAL_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, - if(CMAKE_BUILD_TYPE MATCHES Debug) - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") - else() - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") - endif() + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif(CGAL_HEADER_ONLY) # GMP and GMPXX are not required, but if present, CGAL will link with them. -- cgit v1.2.3 From fa19484e31dbe0b63d50475f15e654a5e1a0c4e1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 4 Sep 2018 09:34:24 +0000 Subject: Use debug or release version to link with python package git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3871 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: afbd5c833ddc3a525d7091ab186714825109eb87 --- CMakeGUDHIVersion.txt | 2 +- src/cython/CMakeLists.txt | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'src/cython') diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index 3ddc907a..ebaddd47 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,6 +1,6 @@ set (GUDHI_MAJOR_VERSION 2) set (GUDHI_MINOR_VERSION 3) -set (GUDHI_PATCH_VERSION 0.rc3) +set (GUDHI_PATCH_VERSION 0) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index cf57d872..09ea28f1 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -130,7 +130,11 @@ if(CYTHON_FOUND) if(CGAL_FOUND) can_cgal_use_cxx11_thread_local() if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") + else() + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") + endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif() # Add CGAL compilation args @@ -142,7 +146,11 @@ if(CYTHON_FOUND) add_gudhi_cython_lib("${CGAL_LIBRARY}") set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") # If CGAL is not header only, CGAL library may link with boost system, - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") + else() + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") endif(CGAL_HEADER_ONLY) # GMP and GMPXX are not required, but if present, CGAL will link with them. @@ -176,8 +184,13 @@ if(CYTHON_FOUND) if (TBB_FOUND AND WITH_GUDHI_USE_TBB) add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") - add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}") - add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}") + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_gudhi_cython_lib("${TBB_DEBUG_LIBRARY}") + add_gudhi_cython_lib("${TBB_MALLOC_DEBUG_LIBRARY}") + else() + add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}") + add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}") + endif() set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ") set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") endif() -- cgit v1.2.3 From 44aaa06e1da4a2e4557886c9c7096edbe9d00f53 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 10 Sep 2018 08:37:45 +0000 Subject: Doc review : Add a link to scipy.stats.gaussian_kde official documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3878 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: dd6e1a4131be1ed0306a48f9b095e0d09ddee848 --- src/cython/cython/persistence_graphical_tools.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 85d2a5ad..f5550e3a 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -256,8 +256,10 @@ try: or a callable. If a scalar, this will be used directly as kde.factor. If a callable, it should take a gaussian_kde instance as only parameter and return a scalar. If None - (default), 'scott' is used. See scipy.stats.gaussian_kde - documentation for more details. + (default), 'scott' is used. See + `scipy.stats.gaussian_kde documentation + `_ + for more details. :type bw_method: str, scalar or callable, optional. :param max_intervals: maximal number of intervals to display. Selected points are those with the longest life time. Set it -- cgit v1.2.3 From 629a456684e9bbf4c2ef5dbfefebe85e9c04a39d Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 10 Sep 2018 09:23:07 +0000 Subject: Add minimal testing for sparse rips in python git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3879 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 14cde17f1ef634539937b215e82bcfe3c8c784f0 --- src/cython/test/test_rips_complex.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/cython') diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py index 2eb1c61c..73cdac17 100755 --- a/src/cython/test/test_rips_complex.py +++ b/src/cython/test/test_rips_complex.py @@ -67,6 +67,18 @@ def test_filtered_rips_from_points(): assert simplex_tree.num_simplices() == 8 assert simplex_tree.num_vertices() == 4 +def test_sparse_filtered_rips_from_points(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_rips = RipsComplex(points=point_list, max_edge_length=1.0, sparse=.001) + + simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 + def test_rips_from_distance_matrix(): distance_matrix = [[0], [1, 0], -- cgit v1.2.3 From 4bf56301ea1aa0c43855bea88344c80db237adbb Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 10 Sep 2018 09:29:57 +0000 Subject: sparse rips example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3880 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8dfc1b3218d3ac3e97a04bf25e59e2d48fc8db1d --- .../example/sparse_rips_persistence_diagram.py | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100755 src/cython/example/sparse_rips_persistence_diagram.py (limited to 'src/cython') diff --git a/src/cython/example/sparse_rips_persistence_diagram.py b/src/cython/example/sparse_rips_persistence_diagram.py new file mode 100755 index 00000000..3bed87c1 --- /dev/null +++ b/src/cython/example/sparse_rips_persistence_diagram.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Marc Glisse + + Copyright (C) 2016 Inria + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" + +__author__ = "Marc Glisse" +__copyright__ = "Copyright (C) 2016 Inria" +__license__ = "GPL v3" + +print("#####################################################################") +print("RipsComplex creation from points") +rips = gudhi.RipsComplex(points=[[0, 0], [0, 0.1], [1, 0], [0, 1], [1, 1]], + max_edge_length=42, sparse=.5) + +simplex_tree = rips.create_simplex_tree(max_dimension=2) + + +diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0) +print("diag=", diag) + +pplot = gudhi.plot_persistence_diagram(diag) +pplot.show() -- cgit v1.2.3 From bdbbbc71e7d82526b24f76cc3b9916ad53919d41 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 10 Sep 2018 09:32:00 +0000 Subject: Code review : More explicit message when import fails in plot persistence graphical tools git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3881 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 96f9e3da3bd68d6cba65242b9890c4beb463c863 --- src/cython/cython/persistence_graphical_tools.py | 309 ++++++++++++----------- 1 file changed, 161 insertions(+), 148 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index f5550e3a..e66643d2 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -55,39 +55,39 @@ palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', '#000000', '#880000', '#008800', '#000088', '#888800', '#880088', '#008888'] -try: - import matplotlib.pyplot as plt - import matplotlib.patches as mpatches - import numpy as np - import os - - def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, - max_intervals=1000, max_barcodes=1000, - inf_delta=0.1, legend=False): - """This function plots the persistence bar code from persistence values list - or from a :doc:`persistence file `. - - :param persistence: Persistence values list. - :type persistence: list of tuples(dimension, tuple(birth, death)). - :param persistence_file: A :doc:`persistence file ` style name - (reset persistence if both are set). - :type persistence_file: string - :param alpha: barcode transparency value (0.0 transparent through 1.0 - opaque - default is 0.6). - :type alpha: float. - :param max_intervals: maximal number of intervals to display. - Selected points are those with the longest life time. Set it - to 0 to see all. Default value is 1000. - :type max_intervals: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x - inf_delta) above the highest point. A reasonable value is between - 0.05 and 0.5 - default is 0.1. - :type inf_delta: float. - :param legend: Display the dimension color legend (default is False). - :type legend: boolean. - :returns: A matplotlib object containing horizontal bar plot of persistence - (launch `show()` method on it to display it). - """ +def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, + max_intervals=1000, max_barcodes=1000, + inf_delta=0.1, legend=False): + """This function plots the persistence bar code from persistence values list + or from a :doc:`persistence file `. + + :param persistence: Persistence values list. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A :doc:`persistence file ` style name + (reset persistence if both are set). + :type persistence_file: string + :param alpha: barcode transparency value (0.0 transparent through 1.0 + opaque - default is 0.6). + :type alpha: float. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. + :param inf_delta: Infinity is placed at ((max_death - min_birth) x + inf_delta) above the highest point. A reasonable value is between + 0.05 and 0.5 - default is 0.1. + :type inf_delta: float. + :param legend: Display the dimension color legend (default is False). + :type legend: boolean. + :returns: A matplotlib object containing horizontal bar plot of persistence + (launch `show()` method on it to display it). + """ + try: + import matplotlib.pyplot as plt + import matplotlib.patches as mpatches + import numpy as np + import os + if persistence_file is not '': if os.path.isfile(persistence_file): # Reset persistence @@ -143,34 +143,43 @@ try: plt.axis([axis_start, infinity, 0, ind]) return plt - def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, - band=0., max_intervals=1000, max_plots=1000, inf_delta=0.1, legend=False): - """This function plots the persistence diagram from persistence values - list or from a :doc:`persistence file `. - - :param persistence: Persistence values list. - :type persistence: list of tuples(dimension, tuple(birth, death)). - :param persistence_file: A :doc:`persistence file ` style name - (reset persistence if both are set). - :type persistence_file: string - :param alpha: plot transparency value (0.0 transparent through 1.0 - opaque - default is 0.6). - :type alpha: float. - :param band: band (not displayed if :math:`\leq` 0. - default is 0.) - :type band: float. - :param max_intervals: maximal number of intervals to display. - Selected points are those with the longest life time. Set it - to 0 to see all. Default value is 1000. - :type max_intervals: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x - inf_delta) above the highest point. A reasonable value is between - 0.05 and 0.5 - default is 0.1. - :type inf_delta: float. - :param legend: Display the dimension color legend (default is False). - :type legend: boolean. - :returns: A matplotlib object containing diagram plot of persistence - (launch `show()` method on it to display it). - """ + except ImportError: + print("This function is not available, you may be missing numpy and/or matplotlib.") + +def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, + band=0., max_intervals=1000, max_plots=1000, inf_delta=0.1, legend=False): + """This function plots the persistence diagram from persistence values + list or from a :doc:`persistence file `. + + :param persistence: Persistence values list. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A :doc:`persistence file ` style name + (reset persistence if both are set). + :type persistence_file: string + :param alpha: plot transparency value (0.0 transparent through 1.0 + opaque - default is 0.6). + :type alpha: float. + :param band: band (not displayed if :math:`\leq` 0. - default is 0.) + :type band: float. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. + :param inf_delta: Infinity is placed at ((max_death - min_birth) x + inf_delta) above the highest point. A reasonable value is between + 0.05 and 0.5 - default is 0.1. + :type inf_delta: float. + :param legend: Display the dimension color legend (default is False). + :type legend: boolean. + :returns: A matplotlib object containing diagram plot of persistence + (launch `show()` method on it to display it). + """ + try: + import matplotlib.pyplot as plt + import matplotlib.patches as mpatches + import numpy as np + import os + if persistence_file is not '': if os.path.isfile(persistence_file): # Reset persistence @@ -230,104 +239,108 @@ try: plt.axis([axis_start, infinity, axis_start, infinity + delta]) return plt + except ImportError: + print("This function is not available, you may be missing numpy and/or matplotlib.") + +def plot_persistence_density(persistence=[], persistence_file='', + nbins=300, bw_method=None, + max_intervals=1000, dimension=None, + cmap=None, legend=False): + """This function plots the persistence density from persistence + values list or from a :doc:`persistence file `. Be + aware that this function does not distinguish the dimension, it is + up to you to select the required one. + + :param persistence: Persistence values list. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A :doc:`persistence file ` + style name (reset persistence if both are set). + :type persistence_file: string + :param nbins: Evaluate a gaussian kde on a regular grid of nbins x + nbins over data extents (default is 300) + :type nbins: int. + :param bw_method: The method used to calculate the estimator + bandwidth. This can be 'scott', 'silverman', a scalar constant + or a callable. If a scalar, this will be used directly as + kde.factor. If a callable, it should take a gaussian_kde + instance as only parameter and return a scalar. If None + (default), 'scott' is used. See + `scipy.stats.gaussian_kde documentation + `_ + for more details. + :type bw_method: str, scalar or callable, optional. + :param max_intervals: maximal number of intervals to display. + Selected points are those with the longest life time. Set it + to 0 to see all. Default value is 1000. + :type max_intervals: int. + :param dimension: the dimension to be selected in the intervals + (default is None to mix all dimensions). + :type dimension: int. + :param cmap: A matplotlib colormap (default is + matplotlib.pyplot.cm.hot_r). + :type cmap: cf. matplotlib colormap. + :param legend: Display the color bar values (default is False). + :type legend: boolean. + :returns: A matplotlib object containing diagram plot of persistence + (launch `show()` method on it to display it). + """ try: + import matplotlib.pyplot as plt + import numpy as np from scipy.stats import kde + import os import math - def plot_persistence_density(persistence=[], persistence_file='', - nbins=300, bw_method=None, - max_intervals=1000, dimension=None, - cmap=plt.cm.hot_r, legend=False): - """This function plots the persistence density from persistence - values list or from a :doc:`persistence file `. Be - aware that this function does not distinguish the dimension, it is - up to you to select the required one. - - :param persistence: Persistence values list. - :type persistence: list of tuples(dimension, tuple(birth, death)). - :param persistence_file: A :doc:`persistence file ` - style name (reset persistence if both are set). - :type persistence_file: string - :param nbins: Evaluate a gaussian kde on a regular grid of nbins x - nbins over data extents (default is 300) - :type nbins: int. - :param bw_method: The method used to calculate the estimator - bandwidth. This can be 'scott', 'silverman', a scalar constant - or a callable. If a scalar, this will be used directly as - kde.factor. If a callable, it should take a gaussian_kde - instance as only parameter and return a scalar. If None - (default), 'scott' is used. See - `scipy.stats.gaussian_kde documentation - `_ - for more details. - :type bw_method: str, scalar or callable, optional. - :param max_intervals: maximal number of intervals to display. - Selected points are those with the longest life time. Set it - to 0 to see all. Default value is 1000. - :type max_intervals: int. - :param dimension: the dimension to be selected in the intervals - (default is None to mix all dimensions). - :type dimension: int. - :param cmap: A matplotlib colormap (default is - matplotlib.pyplot.cm.hot_r). - :type cmap: cf. matplotlib colormap. - :param legend: Display the color bar values (default is False). - :type legend: boolean. - :returns: A matplotlib object containing diagram plot of persistence - (launch `show()` method on it to display it). - """ - if persistence_file is not '': - if os.path.isfile(persistence_file): - # Reset persistence - persistence = [] - diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) - for key in diag.keys(): - for persistence_interval in diag[key]: - persistence.append((key, persistence_interval)) - else: - print("file " + persistence_file + " not found.") - return None - - persistence_dim = [] - if dimension is not None: - persistence_dim = [(dim_interval) for dim_interval in persistence if (dim_interval[0] == dimension)] + if persistence_file is not '': + if os.path.isfile(persistence_file): + # Reset persistence + persistence = [] + diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) + for key in diag.keys(): + for persistence_interval in diag[key]: + persistence.append((key, persistence_interval)) else: - persistence_dim = persistence + print("file " + persistence_file + " not found.") + return None - if max_intervals > 0 and max_intervals < len(persistence_dim): - # Sort by life time, then takes only the max_intervals elements - persistence_dim = sorted(persistence_dim, - key=lambda life_time: life_time[1][1]-life_time[1][0], - reverse=True)[:max_intervals] + persistence_dim = [] + if dimension is not None: + persistence_dim = [(dim_interval) for dim_interval in persistence if (dim_interval[0] == dimension)] + else: + persistence_dim = persistence - # Set as numpy array birth and death (remove undefined values - inf and NaN) - birth = np.asarray([(interval[1][0]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) - death = np.asarray([(interval[1][1]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + if max_intervals > 0 and max_intervals < len(persistence_dim): + # Sort by life time, then takes only the max_intervals elements + persistence_dim = sorted(persistence_dim, + key=lambda life_time: life_time[1][1]-life_time[1][0], + reverse=True)[:max_intervals] - # line display of equation : birth = death - x = np.linspace(death.min(), birth.max(), 1000) - plt.plot(x, x, color='k', linewidth=1.0) + # Set as numpy array birth and death (remove undefined values - inf and NaN) + birth = np.asarray([(interval[1][0]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) + death = np.asarray([(interval[1][1]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))]) - # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents - k = kde.gaussian_kde([birth,death], bw_method=bw_method) - xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] - zi = k(np.vstack([xi.flatten(), yi.flatten()])) + # line display of equation : birth = death + x = np.linspace(death.min(), birth.max(), 1000) + plt.plot(x, x, color='k', linewidth=1.0) - # Make the plot - plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap) + # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents + k = kde.gaussian_kde([birth,death], bw_method=bw_method) + xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j] + zi = k(np.vstack([xi.flatten(), yi.flatten()])) - if legend: - plt.colorbar() + # default cmap value cannot be done at argument definition level as matplotlib is not yet defined. + if cmap is None: + cmap = plt.cm.hot_r + # Make the plot + plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap) - plt.title('Persistence density') - plt.xlabel('Birth') - plt.ylabel('Death') - return plt + if legend: + plt.colorbar() - except ImportError: - # Continue in case of import error, functions won't be available - pass + plt.title('Persistence density') + plt.xlabel('Birth') + plt.ylabel('Death') + return plt -except ImportError: - # Continue in case of import error, functions won't be available - pass + except ImportError: + print("This function is not available, you may be missing numpy, matplotlib and/or scipy.") -- cgit v1.2.3 From 24683e8d0134e7ede7033f05b83c44dd72ff7e3a Mon Sep 17 00:00:00 2001 From: mcarrier Date: Tue, 18 Sep 2018 22:01:20 +0000 Subject: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Nerve_GIC@3897 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f5fe42a6f42443ca7217c69f8a18780cdb85669e --- src/Nerve_GIC/include/gudhi/GIC.h | 18 ++++++++++++++++++ src/cython/cython/nerve_gic.pyx | 9 +++++++++ 2 files changed, 27 insertions(+) (limited to 'src/cython') diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h index 2c37dfae..242ecf7d 100644 --- a/src/Nerve_GIC/include/gudhi/GIC.h +++ b/src/Nerve_GIC/include/gudhi/GIC.h @@ -389,6 +389,24 @@ class Cover_complex { distances[index[boost::source(*ei, one_skeleton)]][index[boost::target(*ei, one_skeleton)]]); } + public: + /** \brief Reads and stores the distance matrices from vector stored in memory. + * + * @param[in] distance_matrix input vector representing the distance matrix. + * + */ + template + void set_distances_from_range(InputRange const & distance_matrix) { + n = distance_matrix.size(); data_dimension = 0; point_cloud_name = "matrix"; + for(int i = 0; i < n; i++){ + point_cloud.emplace_back(); + boost::add_vertex(one_skeleton_OFF); + vertices.push_back(boost::add_vertex(one_skeleton)); + cover.emplace_back(); + } + distances = distance_matrix; + } + public: // Pairwise distances. /** \private \brief Computes all pairwise distances. */ diff --git a/src/cython/cython/nerve_gic.pyx b/src/cython/cython/nerve_gic.pyx index 01dd0a4b..5f01b379 100644 --- a/src/cython/cython/nerve_gic.pyx +++ b/src/cython/cython/nerve_gic.pyx @@ -68,6 +68,7 @@ cdef extern from "Nerve_gic_interface.h" namespace "Gudhi": void plot_DOT() void plot_OFF() void set_point_cloud_from_range(vector[vector[double]] cloud) + void set_distances_from_range(vector[vector[double]] distance_matrix) # CoverComplex python interface cdef class CoverComplex: @@ -111,6 +112,14 @@ cdef class CoverComplex: """ return self.thisptr.set_point_cloud_from_range(cloud) + def set_distances_from_range(self, distance_matrix): + """ Reads and stores the input distance matrix from a vector stored in memory. + + :param distance_matrix: Input vector containing the distance matrix. + :type distance_matrix: vector[vector[double]] + """ + return self.thisptr.set_distances_from_range(distance_matrix) + def compute_confidence_level_from_distance(self, distance): """Computes the confidence level of a specific bottleneck distance threshold. -- cgit v1.2.3 From d95c0d8f3d28067527116a2c1eac06f5bf083995 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 28 Sep 2018 09:00:25 +0000 Subject: https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/32 - [Cmake - Qt5] CMake outputs an error when Qt5 is not installed Modify/add cmake messages for missing modules git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/cmake_missing_modules_clarification_vincent@3912 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 37e1035f7c27ce994e05386801d72959696de7d4 --- CMakeLists.txt | 12 +- src/CMakeLists.txt | 12 +- src/GudhUI/CMakeLists.txt | 81 ++- src/cmake/modules/GUDHI_doxygen_target.cmake | 8 +- src/cmake/modules/GUDHI_modules.cmake | 5 +- .../modules/GUDHI_third_party_libraries.cmake | 4 +- src/cython/CMakeLists.txt | 681 +++++++++++---------- 7 files changed, 434 insertions(+), 369 deletions(-) (limited to 'src/cython') diff --git a/CMakeLists.txt b/CMakeLists.txt index afacede9..d61df992 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,10 @@ include(CMakeGUDHIVersion.txt) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") +# Reset cache +set(GUDHI_MODULES "" CACHE INTERNAL "GUDHI_MODULES") +set(GUDHI_MISSING_MODULES "" CACHE INTERNAL "GUDHI_MISSING_MODULES") + # This variable is used by Cython CMakeLists.txt and by GUDHI_third_party_libraries to know its path set(GUDHI_CYTHON_PATH "src/cython") @@ -37,8 +41,6 @@ add_gudhi_module(Tangential_complex) add_gudhi_module(Witness_complex) add_gudhi_module(Nerve_GIC) -message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") - # Include module CMake subdirectories # GUDHI_SUB_DIRECTORIES is managed in CMAKE_MODULE_PATH/GUDHI_modules.cmake foreach(GUDHI_MODULE ${GUDHI_MODULES}) @@ -54,9 +56,15 @@ add_subdirectory(src/GudhUI) if (WITH_GUDHI_PYTHON) # specific for cython module add_subdirectory(${GUDHI_CYTHON_PATH}) +else() + message("++ Python module will not be compiled because WITH_GUDHI_PYTHON is set to OFF") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python") endif() # For "make user_version" - Requires GUDHI_modules to be performed include(GUDHI_user_version_target) # For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set - Done in GUDHI_user_version_target for dev version include(GUDHI_doxygen_target) + +message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") +message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c446104..b40d506a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,9 @@ include(CMakeGUDHIVersion.txt) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") +set(GUDHI_MODULES "" CACHE INTERNAL "GUDHI_MODULES") +set(GUDHI_MISSING_MODULES "" CACHE INTERNAL "GUDHI_MISSING_MODULES") + # This variable is used by Cython CMakeLists.txt and by GUDHI_third_party_libraries to know its path set(GUDHI_CYTHON_PATH "cython") @@ -35,8 +38,6 @@ add_gudhi_module(Tangential_complex) add_gudhi_module(Witness_complex) add_gudhi_module(Nerve_GIC) -message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") - # For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set set(GUDHI_USER_VERSION_DIR ${CMAKE_SOURCE_DIR}) include(GUDHI_doxygen_target) @@ -60,7 +61,14 @@ add_subdirectory(GudhUI) if (WITH_GUDHI_PYTHON) # specific for cython module add_subdirectory(${GUDHI_CYTHON_PATH}) +else() + message("++ Python module will not be compiled because WITH_GUDHI_PYTHON is set to OFF") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python") endif() + +message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") +message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"") + #--------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------- diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index b357b8f7..0945e758 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -1,40 +1,55 @@ project(GudhUI) # Need to find OpenGL first as find_package(Qt5) tries to #include"GL/gl.h" on some platforms -find_package(OpenGL) +find_package(OpenGL QUIET) if (OPENGL_FOUND) - find_package(Qt5 COMPONENTS Widgets Xml OpenGL) - find_package(QGLViewer) - - if ( CGAL_FOUND AND Qt5_FOUND AND QGLVIEWER_FOUND AND NOT CGAL_VERSION VERSION_EQUAL 4.8.0) - - set(CMAKE_AUTOMOC ON) - set(CMAKE_AUTOUIC ON) - set(CMAKE_INCLUDE_CURRENT_DIR ON) - - SET(Boost_USE_STATIC_LIBS ON) - SET(Boost_USE_MULTITHREAD OFF) - include_directories (${QGLVIEWER_INCLUDE_DIR}) - - add_executable ( GudhUI - gui/gudhui.cpp - gui/MainWindow.cpp - gui/Menu_k_nearest_neighbors.cpp - gui/Menu_uniform_neighbors.cpp - gui/Menu_edge_contraction.cpp - gui/Menu_persistence.cpp - view/Viewer_instructor.cpp - view/Viewer.cpp - ) - target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL ) - target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} ) - target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) - if (TBB_FOUND) - target_link_libraries( GudhUI ${TBB_LIBRARIES}) + find_package(Qt5 COMPONENTS Widgets Xml OpenGL QUIET) + if (Qt5_FOUND) + find_package(QGLViewer QUIET) + if ( QGLVIEWER_FOUND) + + if ( CGAL_FOUND AND NOT CGAL_VERSION VERSION_EQUAL 4.8.0) + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTOUIC ON) + set(CMAKE_INCLUDE_CURRENT_DIR ON) + + SET(Boost_USE_STATIC_LIBS ON) + SET(Boost_USE_MULTITHREAD OFF) + include_directories (${QGLVIEWER_INCLUDE_DIR}) + + add_executable ( GudhUI + gui/gudhui.cpp + gui/MainWindow.cpp + gui/Menu_k_nearest_neighbors.cpp + gui/Menu_uniform_neighbors.cpp + gui/Menu_edge_contraction.cpp + gui/Menu_persistence.cpp + view/Viewer_instructor.cpp + view/Viewer.cpp + ) + target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL ) + target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} ) + target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) + if (TBB_FOUND) + target_link_libraries( GudhUI ${TBB_LIBRARIES}) + endif() + + install(TARGETS GudhUI DESTINATION bin) + set(GUDHI_MODULES ${GUDHI_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MODULES") + else() + message("++ GudhUI will not be compiled because CGAL < 4.8.0 or not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif() + else() + message("++ GudhUI will not be compiled because QGLViewer is not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES") endif() - - install(TARGETS GudhUI DESTINATION bin) - + else() + message("++ GudhUI will not be compiled because Qt5 COMPONENTS Widgets Xml OpenGL are not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES") endif() -endif(OPENGL_FOUND) +else() + message("++ GudhUI will not be compiled because OpenGL is not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES") +endif() diff --git a/src/cmake/modules/GUDHI_doxygen_target.cmake b/src/cmake/modules/GUDHI_doxygen_target.cmake index 9e10e566..7a84c4e0 100644 --- a/src/cmake/modules/GUDHI_doxygen_target.cmake +++ b/src/cmake/modules/GUDHI_doxygen_target.cmake @@ -1,7 +1,7 @@ # add a target to generate API documentation with Doxygen -find_package(Doxygen) +find_package(Doxygen QUIET) if(DOXYGEN_FOUND) - # configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + set(GUDHI_MODULES ${GUDHI_MODULES} "cpp-documentation" CACHE INTERNAL "GUDHI_MODULES") # starting from cmake 3.9 the usage of DOXYGEN_EXECUTABLE is deprecated if(TARGET Doxygen::doxygen) @@ -16,4 +16,6 @@ if(DOXYGEN_FOUND) # In dev version, doxygen target depends on user_version target. Not existing in user version add_dependencies(doxygen user_version) endif() -endif(DOXYGEN_FOUND) +else() + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "cpp-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") +endif() diff --git a/src/cmake/modules/GUDHI_modules.cmake b/src/cmake/modules/GUDHI_modules.cmake index f95d0c34..aab1dd08 100644 --- a/src/cmake/modules/GUDHI_modules.cmake +++ b/src/cmake/modules/GUDHI_modules.cmake @@ -1,11 +1,12 @@ # A function to add a new module in GUDHI -set(GUDHI_MODULES "") set(GUDHI_MODULES_FULL_LIST "") function(add_gudhi_module file_path) option("WITH_MODULE_GUDHI_${file_path}" "Activate/desactivate ${file_path} compilation and installation" ON) if (WITH_MODULE_GUDHI_${file_path}) - set(GUDHI_MODULES ${GUDHI_MODULES} ${file_path} PARENT_SCOPE) + set(GUDHI_MODULES ${GUDHI_MODULES} ${file_path} CACHE INTERNAL "GUDHI_MODULES") + else() + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} ${file_path} CACHE INTERNAL "GUDHI_MISSING_MODULES") endif() # Required by user_version set(GUDHI_MODULES_FULL_LIST ${GUDHI_MODULES_FULL_LIST} ${file_path} PARENT_SCOPE) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index f03c2177..122754d5 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -21,11 +21,11 @@ endif() # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html # but it implies to use cmake version 3.1 at least. -find_package(CGAL) +find_package(CGAL QUIET) # Only CGAL versions > 4.4 supports what Gudhi uses from CGAL if (CGAL_VERSION VERSION_LESS 4.4.0) - message("CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.") + message("++ CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.") unset(CGAL_FOUND) endif() if(CGAL_FOUND) diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 09ea28f1..8fcd6cbf 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -31,375 +31,406 @@ function( add_gudhi_debug_info DEBUG_INFO ) set(GUDHI_CYTHON_DEBUG_INFO "${GUDHI_CYTHON_DEBUG_INFO} \"${DEBUG_INFO}\\n\" \\\n" PARENT_SCOPE) endfunction( add_gudhi_debug_info ) - -if(CYTHON_FOUND) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}off_reader;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}simplex_tree;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}rips_complex;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}cubical_complex;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}periodic_cubical_complex;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}reader_utils;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}witness_complex;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}strong_witness_complex;") - - add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") - add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") - if(PYTEST_FOUND) - add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}") - endif() - if(MATPLOTLIB_FOUND) - add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}") - endif() - if(NUMPY_FOUND) - add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") - endif() - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) +if(PYTHONINTERP_FOUND) + if(CYTHON_FOUND) + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}off_reader;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}simplex_tree;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}rips_complex;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}cubical_complex;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}periodic_cubical_complex;") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") - endif() + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}reader_utils;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}witness_complex;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}strong_witness_complex;") + + add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") + add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") + if(PYTEST_FOUND) + add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}") + endif() + if(MATPLOTLIB_FOUND) + add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}") + endif() + if(NUMPY_FOUND) + add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") + endif() + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") + else() + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;") + endif() - message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_VERSION} - Sphinx is ${SPHINX_PATH}") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ") - - # Gudhi and CGAL compilation option - if(MSVC) - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") - else(MSVC) - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ") - endif(MSVC) - if(CMAKE_COMPILER_IS_GNUCXX) - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") - endif(CMAKE_COMPILER_IS_GNUCXX) - if (CMAKE_CXX_COMPILER_ID MATCHES Intel) - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") - endif(CMAKE_CXX_COMPILER_ID MATCHES Intel) - if (DEBUG_TRACES) - # For programs to be more verbose - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") - endif() + message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_VERSION} - Sphinx is ${SPHINX_PATH}") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ") + + # Gudhi and CGAL compilation option + if(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") + else(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ") + endif(MSVC) + if(CMAKE_COMPILER_IS_GNUCXX) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") + endif(CMAKE_COMPILER_IS_GNUCXX) + if (CMAKE_CXX_COMPILER_ID MATCHES Intel) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") + endif(CMAKE_CXX_COMPILER_ID MATCHES Intel) + if (DEBUG_TRACES) + # For programs to be more verbose + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") + endif() - if (EIGEN3_FOUND) - add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") - # No problem, even if no CGAL found - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") - endif (EIGEN3_FOUND) - - if (NOT CGAL_VERSION VERSION_LESS 4.8.1) - set(GUDHI_CYTHON_BOTTLENECK_DISTANCE "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/bottleneck_distance.pyx'") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}bottleneck_distance;") - set(GUDHI_CYTHON_NERVE_GIC "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/nerve_gic.pyx'") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}nerve_gic;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}bottleneck_distance;") - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}nerve_gic;") - endif () - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) - set(GUDHI_CYTHON_SUBSAMPLING "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/subsampling.pyx'") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}subsampling;") - set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/tangential_complex.pyx'") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}tangential_complex;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}subsampling;") - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}tangential_complex;") - endif () - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) - set(GUDHI_CYTHON_ALPHA_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/alpha_complex.pyx'") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}alpha_complex;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}alpha_complex;") - endif () - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) - set(GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX - "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_witness_complex.pyx'\ninclude '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_strong_witness_complex.pyx'\n") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_witness_complex;") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_strong_witness_complex;") - else() - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_witness_complex;") - set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_strong_witness_complex;") - endif () - - add_gudhi_debug_info("Installed modules are: ${GUDHI_CYTHON_MODULES}") - if(GUDHI_CYTHON_MISSING_MODULES) - add_gudhi_debug_info("Missing modules are: ${GUDHI_CYTHON_MISSING_MODULES}") - endif() + if (EIGEN3_FOUND) + add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") + # No problem, even if no CGAL found + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + endif (EIGEN3_FOUND) + + if (NOT CGAL_VERSION VERSION_LESS 4.8.1) + set(GUDHI_CYTHON_BOTTLENECK_DISTANCE "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/bottleneck_distance.pyx'") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}bottleneck_distance;") + set(GUDHI_CYTHON_NERVE_GIC "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/nerve_gic.pyx'") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}nerve_gic;") + else() + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}bottleneck_distance;") + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}nerve_gic;") + endif () + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + set(GUDHI_CYTHON_SUBSAMPLING "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/subsampling.pyx'") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}subsampling;") + set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/tangential_complex.pyx'") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}tangential_complex;") + else() + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}subsampling;") + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}tangential_complex;") + endif () + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) + set(GUDHI_CYTHON_ALPHA_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/alpha_complex.pyx'") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}alpha_complex;") + else() + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}alpha_complex;") + endif () + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) + set(GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX + "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_witness_complex.pyx'\ninclude '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_strong_witness_complex.pyx'\n") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_witness_complex;") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_strong_witness_complex;") + else() + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_witness_complex;") + set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_strong_witness_complex;") + endif () - if(CGAL_FOUND) - can_cgal_use_cxx11_thread_local() - if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) - if(CMAKE_BUILD_TYPE MATCHES Debug) - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") - else() - add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") - endif() - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") + add_gudhi_debug_info("Installed modules are: ${GUDHI_CYTHON_MODULES}") + if(GUDHI_CYTHON_MISSING_MODULES) + add_gudhi_debug_info("Missing modules are: ${GUDHI_CYTHON_MISSING_MODULES}") endif() - # Add CGAL compilation args - if(CGAL_HEADER_ONLY) - add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") - else(CGAL_HEADER_ONLY) - add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - add_gudhi_cython_lib("${CGAL_LIBRARY}") - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") - # If CGAL is not header only, CGAL library may link with boost system, + + if(CGAL_FOUND) + can_cgal_use_cxx11_thread_local() + if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT) + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}") + else() + add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}") + endif() + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") + endif() + # Add CGAL compilation args + if(CGAL_HEADER_ONLY) + add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") + else(CGAL_HEADER_ONLY) + add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") + add_gudhi_cython_lib("${CGAL_LIBRARY}") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") + # If CGAL is not header only, CGAL library may link with boost system, + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") + else() + add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + endif() + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") + endif(CGAL_HEADER_ONLY) + # GMP and GMPXX are not required, but if present, CGAL will link with them. + if(GMP_FOUND) + add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") + add_gudhi_cython_lib("${GMP_LIBRARIES}") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") + if(GMPXX_FOUND) + add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") + add_gudhi_cython_lib("${GMPXX_LIBRARIES}") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") + endif(GMPXX_FOUND) + endif(GMP_FOUND) + endif(CGAL_FOUND) + + # Specific for Mac + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=10.12', ") + set(GUDHI_CYTHON_EXTRA_LINK_ARGS "${GUDHI_CYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=10.12', ") + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + # Loop on INCLUDE_DIRECTORIES PROPERTY + get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) + foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") + endforeach() + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ") + + if (TBB_FOUND AND WITH_GUDHI_USE_TBB) + add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") if(CMAKE_BUILD_TYPE MATCHES Debug) - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") + add_gudhi_cython_lib("${TBB_DEBUG_LIBRARY}") + add_gudhi_cython_lib("${TBB_MALLOC_DEBUG_LIBRARY}") else() - add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}") + add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}") endif() - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") - endif(CGAL_HEADER_ONLY) - # GMP and GMPXX are not required, but if present, CGAL will link with them. - if(GMP_FOUND) - add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") - add_gudhi_cython_lib("${GMP_LIBRARIES}") - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") - if(GMPXX_FOUND) - add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") - add_gudhi_cython_lib("${GMPXX_LIBRARIES}") - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") - endif(GMPXX_FOUND) - endif(GMP_FOUND) - endif(CGAL_FOUND) - - # Specific for Mac - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=10.12', ") - set(GUDHI_CYTHON_EXTRA_LINK_ARGS "${GUDHI_CYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=10.12', ") - endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - - # Loop on INCLUDE_DIRECTORIES PROPERTY - get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) - foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) - set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") - endforeach() - set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ") - - if (TBB_FOUND AND WITH_GUDHI_USE_TBB) - add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used") - set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") - if(CMAKE_BUILD_TYPE MATCHES Debug) - add_gudhi_cython_lib("${TBB_DEBUG_LIBRARY}") - add_gudhi_cython_lib("${TBB_MALLOC_DEBUG_LIBRARY}") - else() - add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}") - add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ") + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") endif() - set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ") - set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") - endif() - if(UNIX) - set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}") - endif(UNIX) - - # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention - configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) - # Generate gudhi.pyx - Gudhi cython file - configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY) - - add_custom_command( - OUTPUT gudhi.so - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace") - - add_custom_target(cython ALL DEPENDS gudhi.so - COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") - - # For installation purpose - # TODO(VR) : files matching pattern mechanism is copying all cython directory - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING - PATTERN "*.so" - PATTERN "*.dylib" - PATTERN "*.pyd") - - # Test examples - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) - # Bottleneck and Alpha - add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" - -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) + if(UNIX) + set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}") + endif(UNIX) + + # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention + configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) + # Generate gudhi.pyx - Gudhi cython file + configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY) + + add_custom_command( + OUTPUT gudhi.so + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace") + + add_custom_target(cython ALL DEPENDS gudhi.so + COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") + + # For installation purpose + # TODO(VR) : files matching pattern mechanism is copying all cython directory + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING + PATTERN "*.so" + PATTERN "*.dylib" + PATTERN "*.pyd") + + # Test examples + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + # Bottleneck and Alpha + add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" + -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) + + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + # Tangential + add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" + --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + + add_gudhi_py_test(test_tangential_complex) + + # Witness complex AND Subsampling + add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + + add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + endif() - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - # Tangential - add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test + # Subsampling + add_gudhi_py_test(test_subsampling) + + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + if (NOT CGAL_VERSION VERSION_LESS 4.8.1) + # Bottleneck + add_test(NAME bottleneck_basic_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" - --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py") - add_gudhi_py_test(test_tangential_complex) + add_gudhi_py_test(test_bottleneck_distance) - # Witness complex AND Subsampling - add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test + # Cover complex + file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + add_test(NAME cover_complex_nerve_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py" + -f human.off -c 2 -r 10 -g 0.3) - add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test + add_test(NAME cover_complex_coordinate_gic_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - endif() + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py" + -f human.off -c 0 -v) - # Subsampling - add_gudhi_py_test(test_subsampling) + add_test(NAME cover_complex_functional_gic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py" + -o lucky_cat.off + -f lucky_cat_PCA1 -v) - endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) - if (NOT CGAL_VERSION VERSION_LESS 4.8.1) - # Bottleneck - add_test(NAME bottleneck_basic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py") + add_test(NAME cover_complex_voronoi_gic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py" + -f human.off -n 700 -v) - add_gudhi_py_test(test_bottleneck_distance) + add_gudhi_py_test(test_cover_complex) + endif (NOT CGAL_VERSION VERSION_LESS 4.8.1) - # Cover complex - file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(NAME cover_complex_nerve_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py" - -f human.off -c 2 -r 10 -g 0.3) + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) + # Alpha + add_test(NAME alpha_complex_from_points_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") - add_test(NAME cover_complex_coordinate_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py" - -f human.off -c 0 -v) + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) + endif() - add_test(NAME cover_complex_functional_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py" - -o lucky_cat.off - -f lucky_cat_PCA1 -v) + add_gudhi_py_test(test_alpha_complex) - add_test(NAME cover_complex_voronoi_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py" - -f human.off -n 700 -v) + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) - add_gudhi_py_test(test_cover_complex) - endif (NOT CGAL_VERSION VERSION_LESS 4.8.1) + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) + # Euclidean witness + add_gudhi_py_test(test_euclidean_witness_complex) - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) - # Alpha - add_test(NAME alpha_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + # Cubical + add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) - endif() - - add_gudhi_py_test(test_alpha_complex) + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" + --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) - endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) + if(NUMPY_FOUND) + add_test(NAME random_cubical_complex_persistence_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py" + 10 10 10) + endif() - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) - # Euclidean witness - add_gudhi_py_test(test_euclidean_witness_complex) + add_gudhi_py_test(test_cubical_complex) - endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) + # Rips + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) - # Cubical - add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" - --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) + add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) + endif() - if(NUMPY_FOUND) - add_test(NAME random_cubical_complex_persistence_example_py_test + add_test(NAME rips_complex_from_points_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py" - 10 10 10) - endif() + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py) - add_gudhi_py_test(test_cubical_complex) + add_gudhi_py_test(test_rips_complex) - # Rips - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) - - add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test + # Simplex tree + add_test(NAME simplex_tree_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) - endif() - - add_test(NAME rips_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py) - - add_gudhi_py_test(test_rips_complex) - - # Simplex tree - add_test(NAME simplex_tree_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py) - - add_gudhi_py_test(test_simplex_tree) + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py) - # Witness - add_test(NAME witness_complex_from_nearest_landmark_table_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py) + add_gudhi_py_test(test_simplex_tree) - add_gudhi_py_test(test_witness_complex) - - # Reader utils - add_gudhi_py_test(test_reader_utils) - - # Documentation generation is available through sphinx - requires all modules - if(SPHINX_PATH AND MATPLOTLIB_FOUND AND NUMPY_FOUND AND NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) - set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") - # User warning - Sphinx is a static pages generator, and configured to work fine with user_version - # Images and biblio warnings because not found on developper version - if (GUDHI_CYTHON_PATH STREQUAL "src/cython") - set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss") - endif() - # sphinx target requires gudhi.so, because conf.py reads gudhi version from it - add_custom_target(sphinx - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx - DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" - COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) - - add_test(NAME sphinx_py_test + # Witness + add_test(NAME witness_complex_from_nearest_landmark_table_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) - - endif() -endif(CYTHON_FOUND) + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py) + + add_gudhi_py_test(test_witness_complex) + + # Reader utils + add_gudhi_py_test(test_reader_utils) + + # Documentation generation is available through sphinx - requires all modules + if(SPHINX_PATH) + if(MATPLOTLIB_FOUND) + if(NUMPY_FOUND) + if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") + # User warning - Sphinx is a static pages generator, and configured to work fine with user_version + # Images and biblio warnings because not found on developper version + if (GUDHI_CYTHON_PATH STREQUAL "src/cython") + set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss") + endif() + # sphinx target requires gudhi.so, because conf.py reads gudhi version from it + add_custom_target(sphinx + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) + + add_test(NAME sphinx_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) + + # Set missing or not modules + set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES") + else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + message("++ Python documentation module will not be compiled because it requires a CGAL with Eigen3 version greater or equal than 4.8.1") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) + else(NUMPY_FOUND) + message("++ Python module will not be compiled because numpy was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(NUMPY_FOUND) + else(MATPLOTLIB_FOUND) + message("++ Python module will not be compiled because matplotlib was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(MATPLOTLIB_FOUND) + else(SPHINX_PATH) + message("++ Python module will not be compiled because sphinx and sphinxcontrib-bibtex were not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(SPHINX_PATH) + + + # Set missing or not modules + set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES") + else(CYTHON_FOUND) + message("++ Python module will not be compiled because cython was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(CYTHON_FOUND) +else(PYTHONINTERP_FOUND) + message("++ Python module will not be compiled because no Python interpreter was found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") +endif(PYTHONINTERP_FOUND) -- cgit v1.2.3 From 2ca563e4e1a12443773cd58ab65ef65286bc31dd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 28 Sep 2018 09:14:37 +0000 Subject: Python Nerve and Graph Induced Complex was introduced in GUDHI 2.3.0 (not 2.1.0) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3914 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8e34cf876daf73288caed371c7ce9c51f07fbf7f --- src/cython/doc/nerve_gic_complex_sum.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/nerve_gic_complex_sum.rst b/src/cython/doc/nerve_gic_complex_sum.rst index 72782c7a..523c119f 100644 --- a/src/cython/doc/nerve_gic_complex_sum.rst +++ b/src/cython/doc/nerve_gic_complex_sum.rst @@ -1,5 +1,5 @@ ================================================================= =================================== =================================== -:Author: Mathieu Carrière :Introduced in: GUDHI 2.1.0 :Copyright: GPL v3 +:Author: Mathieu Carrière :Introduced in: GUDHI 2.3.0 :Copyright: GPL v3 :Requires: CGAL :math:`\geq` 4.8.1 ================================================================= =================================== =================================== -- cgit v1.2.3 From 338b2f41bd14f04193a0b2f6fb0a2321443be45b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Oct 2018 07:45:51 +0000 Subject: Doc review: max_intervals documentation in plot_persistence_density git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3917 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 90cfd77ad4aad4cdb0937f43dd4f802688f98295 --- src/cython/cython/persistence_graphical_tools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index e66643d2..139a2332 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -269,7 +269,8 @@ def plot_persistence_density(persistence=[], persistence_file='', `_ for more details. :type bw_method: str, scalar or callable, optional. - :param max_intervals: maximal number of intervals to display. + :param max_intervals: maximal number of points used in the density + estimation. Selected points are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. -- cgit v1.2.3 From 5469c3637df2efd1a70a165484b992727782d15c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Oct 2018 07:51:22 +0000 Subject: Doc review : "Selected points are" -> "Selected intervals are" git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3918 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 79857a4609428fc623f8f4656762261ea664cf12 --- src/cython/cython/persistence_graphical_tools.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 139a2332..abc205bb 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -70,7 +70,7 @@ def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, opaque - default is 0.6). :type alpha: float. :param max_intervals: maximal number of intervals to display. - Selected points are those with the longest life time. Set it + Selected intervals are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. :param inf_delta: Infinity is placed at ((max_death - min_birth) x @@ -162,7 +162,7 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, :param band: band (not displayed if :math:`\leq` 0. - default is 0.) :type band: float. :param max_intervals: maximal number of intervals to display. - Selected points are those with the longest life time. Set it + Selected intervals are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. :param inf_delta: Infinity is placed at ((max_death - min_birth) x @@ -271,7 +271,7 @@ def plot_persistence_density(persistence=[], persistence_file='', :type bw_method: str, scalar or callable, optional. :param max_intervals: maximal number of points used in the density estimation. - Selected points are those with the longest life time. Set it + Selected intervals are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. :param dimension: the dimension to be selected in the intervals -- cgit v1.2.3 From b4c51b3d92564e2e93e8fa4fe55f98cd06bba57a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Oct 2018 08:13:28 +0000 Subject: Code review : remove executable property Doc review : Rephrase inf_delta explanation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3919 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b45697b675a20cdca7bb42fa7a555df6c35fe0fd --- src/cython/cython/persistence_graphical_tools.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) mode change 100755 => 100644 src/cython/cython/persistence_graphical_tools.py (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py old mode 100755 new mode 100644 index abc205bb..e63b350b --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -61,7 +61,7 @@ def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, """This function plots the persistence bar code from persistence values list or from a :doc:`persistence file `. - :param persistence: Persistence values list. + :param persistence: Persistence intervals values list grouped by dimension. :type persistence: list of tuples(dimension, tuple(birth, death)). :param persistence_file: A :doc:`persistence file ` style name (reset persistence if both are set). @@ -73,9 +73,9 @@ def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, Selected intervals are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x - inf_delta) above the highest point. A reasonable value is between - 0.05 and 0.5 - default is 0.1. + :param inf_delta: Infinity is placed at :code:`((max_death - min_birth) x + inf_delta)` above :code:`max_death` value. A reasonable value is + between 0.05 and 0.5 - default is 0.1. :type inf_delta: float. :param legend: Display the dimension color legend (default is False). :type legend: boolean. @@ -151,7 +151,7 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, """This function plots the persistence diagram from persistence values list or from a :doc:`persistence file `. - :param persistence: Persistence values list. + :param persistence: Persistence intervals values list grouped by dimension. :type persistence: list of tuples(dimension, tuple(birth, death)). :param persistence_file: A :doc:`persistence file ` style name (reset persistence if both are set). @@ -165,9 +165,9 @@ def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, Selected intervals are those with the longest life time. Set it to 0 to see all. Default value is 1000. :type max_intervals: int. - :param inf_delta: Infinity is placed at ((max_death - min_birth) x - inf_delta) above the highest point. A reasonable value is between - 0.05 and 0.5 - default is 0.1. + :param inf_delta: Infinity is placed at :code:`((max_death - min_birth) x + inf_delta)` above :code:`max_death` value. A reasonable value is + between 0.05 and 0.5 - default is 0.1. :type inf_delta: float. :param legend: Display the dimension color legend (default is False). :type legend: boolean. @@ -251,7 +251,7 @@ def plot_persistence_density(persistence=[], persistence_file='', aware that this function does not distinguish the dimension, it is up to you to select the required one. - :param persistence: Persistence values list. + :param persistence: Persistence intervals values list grouped by dimension. :type persistence: list of tuples(dimension, tuple(birth, death)). :param persistence_file: A :doc:`persistence file ` style name (reset persistence if both are set). -- cgit v1.2.3 From 2dde0fc4ea8f24173789a1ce9a9442cb02b96e86 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Oct 2018 08:23:51 +0000 Subject: Doc review : Explain that plot persistence density function doesn't handle degenerate data git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/plot_persistence_density_vincent@3920 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7794f7959b98b0245e26077d2f2639f33655d5c9 --- src/cython/cython/persistence_graphical_tools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index e63b350b..d7be936f 100644 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -249,7 +249,8 @@ def plot_persistence_density(persistence=[], persistence_file='', """This function plots the persistence density from persistence values list or from a :doc:`persistence file `. Be aware that this function does not distinguish the dimension, it is - up to you to select the required one. + up to you to select the required one. This function also does not handle + degenerate data set (scipy correlation matrix inversion can fail). :param persistence: Persistence intervals values list grouped by dimension. :type persistence: list of tuples(dimension, tuple(birth, death)). -- cgit v1.2.3 From 42e599ebd89231c276a3c6e1b9121ea13f25d118 Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 2 Oct 2018 09:21:13 +0000 Subject: More doc changes for python sparse rips git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3921 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f9a33e3c4a6fc6d68a81b753a88ff9d39bdcfb9f --- biblio/bibliography.bib | 3 +- src/Rips_complex/doc/Intro_rips_complex.h | 2 +- src/cython/cython/rips_complex.pyx | 3 +- src/cython/doc/rips_complex_user.rst | 52 ++++++++++++++++++++----------- 4 files changed, 38 insertions(+), 22 deletions(-) (limited to 'src/cython') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 16f43d6f..e85876d3 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1073,9 +1073,10 @@ language={English} @article{buchet16efficient, title = {Efficient and Robust Persistent Homology for Measures}, author = {Micka\"{e}l Buchet and Fr\'{e}d\'{e}ric Chazal and Steve Y. Oudot and Donald Sheehy}, - booktitle = {Computational Geometry: Theory and Applications}, + journal = {Computational Geometry: Theory and Applications}, volume = {58}, pages = {70--96}, + doi = "https://doi.org/10.1016/j.comgeo.2016.07.001", year = {2016} } diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 3db5287e..e54ae57c 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -39,7 +39,7 @@ namespace rips_complex { * (Wikipedia) * is an abstract simplicial complex * defined on a finite metric space, where each simplex corresponds to a subset - * of point whose diameter is smaller that some given threshold. + * of points whose diameter is smaller that some given threshold. * Varying the threshold, we can also see the Rips complex as a filtration of * the \f$(n-1)-\f$dimensional simplex, where the filtration value of each * simplex is the diameter of the corresponding subset of points. diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index 620130ca..ecf039b6 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -62,8 +62,7 @@ cdef class RipsComplex: Or - :param distance_matrix: A distance matrix (full square or lower - triangular). + :param distance_matrix: A distance matrix (full square or lower triangular). :type points: list of list of double And in both cases diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index a8c06cf9..9fa3a677 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -7,27 +7,22 @@ Rips complex user manual Definition ---------- -======================================================= ===================================== ===================================== -:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -======================================================= ===================================== ===================================== +==================================================================== ================================ ====================== +:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +==================================================================== ================================ ====================== +-------------------------------------------+----------------------------------------------------------------------+ | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -`Rips complex `_ is a one skeleton graph that allows to -construct a simplicial complex from it. The input can be a point cloud with a given distance function, or a distance -matrix. +The `Rips complex `_ is a simplicial complex defined as the clique complex of a graph. The graph is defined on a set of points with one vertex for each point and an edge between any 2 points, of weight (aka filtration value) the distance between the 2 points. This graph (and thus the complex) can be restricted to edges shorter than some threshold, to reduce its size. -The filtration value of each edge is computed from a user-given distance function, or directly from the distance -matrix. +The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -All edges that have a filtration value strictly greater than a given threshold value are not inserted into the complex. +When creating a simplicial complex from the graph, `RipsComplex` inserts the graph into the data +structure, and then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. -When creating a simplicial complex from this one skeleton graph, Rips inserts the one skeleton graph into the data -structure, and then expands the simplicial complex when required. - -Vertex name correspond to the index of the point in the given range (aka. the point cloud). +A vertex name corresponds to the index of the point in the given range (aka. the point cloud). .. figure:: ../../doc/Rips_complex/rips_complex_representation.png @@ -38,8 +33,27 @@ Vertex name correspond to the index of the point in the given range (aka. the po On this example, as edges (4,5), (4,6) and (5,6) are in the complex, simplex (4,5,6) is added with the filtration value set with :math:`max(filtration(4,5), filtration(4,6), filtration(5,6))`. And so on for simplex (0,1,2,3). -If the Rips_complex interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp -example, where the graph construction over the Simplex_tree is more detailed. +If the `RipsComplex` interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp +C++ example, where the graph construction over the Simplex_tree is more detailed. + +A Rips complex can easily become huge, even if we limit the length of the edges +and the dimension of the simplices. One easy trick, before building a Rips +complex on a point cloud, is to call `sparsify_point_set` which removes points +that are too close to each other. This does not change its persistence diagram +by more than the length used to define "too close". + +A more general technique is to use a sparse approximation of the Rips +introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version +described in :cite:`buchet16efficient` (except that we multiply all filtration +values by 2, to match the usual Rips complex), which proves a +:math:`\frac{1+\epsilon}{1-\epsilon}`-interleaving, although in practice the +error is usually smaller. A more intuitive presentation of the idea is +available in :cite:`cavanna15geometric`, and in a video +:cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the +construction of a `RipsComplex` object asks it to build a sparse Rips with +parameter `ε=0.3`, while the default `sparse=None` builds the +regular Rips complex. + Point cloud ----------- @@ -47,7 +61,7 @@ Point cloud Example from a point cloud ^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example builds the one skeleton graph from the given points, and max_edge_length value. +This example builds the neighborhood graph from the given points, up to max_edge_length. Then it creates a :doc:`Simplex_tree ` with it. Finally, it is asked to display information about the simplicial complex. @@ -92,10 +106,12 @@ until dimension 1 - one skeleton graph in other words), the output is: [4, 6] -> 9.49 [3, 6] -> 11.00 +Notice that if we use `rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2)`, asking for very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. + Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -This example builds the :doc:`Rips_complex ` from the given +This example builds the :doc:`RipsComplex ` from the given points in an OFF file, and max_edge_length value. Then it creates a :doc:`Simplex_tree ` with it. @@ -200,7 +216,7 @@ until dimension 1 - one skeleton graph in other words), the output is: Example from csv file ^^^^^^^^^^^^^^^^^^^^^ -This example builds the :doc:`Rips_complex ` from the given +This example builds the :doc:`RipsComplex ` from the given distance matrix in a csv file, and max_edge_length value. Then it creates a :doc:`Simplex_tree ` with it. -- cgit v1.2.3 From cae07e49a1700613bf709f7d0bbf3d1c640d4a2c Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 2 Oct 2018 11:09:47 +0000 Subject: Catch exception by const& git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3922 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1b0cea99516d6b42e5ab3b0fdb21468b321e6d6c --- src/cython/include/Alpha_complex_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/include/Alpha_complex_interface.h b/src/cython/include/Alpha_complex_interface.h index 8cf527fc..faa059d1 100644 --- a/src/cython/include/Alpha_complex_interface.h +++ b/src/cython/include/Alpha_complex_interface.h @@ -60,7 +60,7 @@ class Alpha_complex_interface { Point_d ph = alpha_complex_->get_point(vh); for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) vd.push_back(*coord); - } catch (std::out_of_range outofrange) { + } catch (std::out_of_range const&) { // std::out_of_range is thrown in case not found. Other exceptions must be re-thrown } return vd; -- cgit v1.2.3 From 9e7c5464fd0f3e12e0b309e7b8ebbad1f830e4a7 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 5 Oct 2018 13:43:21 +0000 Subject: pasto git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3933 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3fc8b696f0c457256e0c8bf74ffffa580dbb69d4 --- src/cython/cython/simplex_tree.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx index e302486b..8397d9d9 100644 --- a/src/cython/cython/simplex_tree.pyx +++ b/src/cython/cython/simplex_tree.pyx @@ -515,7 +515,7 @@ cdef class SimplexTree: :returns: The persistence intervals. :rtype: list of pair of list of int - :note: intervals_in_dim function requires + :note: persistence_pairs function requires :func:`persistence()` function to be launched first. """ -- cgit v1.2.3 From 0567f550258966a12911cd3ffe490852c022c358 Mon Sep 17 00:00:00 2001 From: glisse Date: Sat, 6 Oct 2018 14:01:16 +0000 Subject: Doc tweaks. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3936 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3c75c674876bcb38d0a87de41d406832baf61b55 --- biblio/bibliography.bib | 2 ++ src/cython/cython/rips_complex.pyx | 1 + src/cython/doc/rips_complex_user.rst | 5 ++--- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index e85876d3..a8c040ed 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1084,6 +1084,7 @@ language={English} author = {Nicholas J. Cavanna and Mahmoodreza Jahanseir and Donald R. Sheehy}, booktitle = {Proceedings of the Canadian Conference on Computational Geometry}, title = {A Geometric Perspective on Sparse Filtrations}, + url = {http://research.cs.queensu.ca/cccg2015/CCCG15-papers/01.pdf}, year = {2015} } @@ -1102,5 +1103,6 @@ language={English} volume = {49}, number = {4}, pages = {778--796}, + doi = "10.1007/s00454-013-9513-1", year = {2013} } diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index ecf039b6..cb9aad2e 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -66,6 +66,7 @@ cdef class RipsComplex: :type points: list of list of double And in both cases + :param sparse: If this is not None, it switches to building a sparse Rips and represents the approximation parameter epsilon. :type sparse: float """ diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 9fa3a677..95bb40b6 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -15,12 +15,11 @@ Definition | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -The `Rips complex `_ is a simplicial complex defined as the clique complex of a graph. The graph is defined on a set of points with one vertex for each point and an edge between any 2 points, of weight (aka filtration value) the distance between the 2 points. This graph (and thus the complex) can be restricted to edges shorter than some threshold, to reduce its size. +The `Rips complex `_ is a simplicial complex that generalizes proximity (ε-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -When creating a simplicial complex from the graph, `RipsComplex` inserts the graph into the data -structure, and then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. +When creating a simplicial complex from the graph, `RipsComplex` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. A vertex name corresponds to the index of the point in the given range (aka. the point cloud). -- cgit v1.2.3 From c537a466ffdd812d92098bcea04cdf6f0bfc64ec Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:17:19 +0000 Subject: Example text and copyright year git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3937 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6d5bf6a2c55f7c4fd4f3f5159651b3ffa057ffdd --- src/cython/example/sparse_rips_persistence_diagram.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/example/sparse_rips_persistence_diagram.py b/src/cython/example/sparse_rips_persistence_diagram.py index 3bed87c1..d58c244c 100755 --- a/src/cython/example/sparse_rips_persistence_diagram.py +++ b/src/cython/example/sparse_rips_persistence_diagram.py @@ -8,7 +8,7 @@ import gudhi Author(s): Marc Glisse - Copyright (C) 2016 Inria + Copyright (C) 2018 Inria This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,11 +25,11 @@ import gudhi """ __author__ = "Marc Glisse" -__copyright__ = "Copyright (C) 2016 Inria" +__copyright__ = "Copyright (C) 2018 Inria" __license__ = "GPL v3" print("#####################################################################") -print("RipsComplex creation from points") +print("Sparse RipsComplex creation from points") rips = gudhi.RipsComplex(points=[[0, 0], [0, 0.1], [1, 0], [0, 1], [1, 1]], max_edge_length=42, sparse=.5) -- cgit v1.2.3 From d16910a5c74552b3b1feffc3e793ec5b6d52f952 Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:43:35 +0000 Subject: Use math instead of unicode for epsilon git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3938 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8cccce774b7406d90a55d0e2827fad6dc3855b39 --- src/cython/doc/rips_complex_user.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 95bb40b6..cddf4f16 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -45,7 +45,7 @@ A more general technique is to use a sparse approximation of the Rips introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version described in :cite:`buchet16efficient` (except that we multiply all filtration values by 2, to match the usual Rips complex), which proves a -:math:`\frac{1+\epsilon}{1-\epsilon}`-interleaving, although in practice the +:math:`\frac{1+\varepsilon}{1-\varepsilon}`-interleaving, although in practice the error is usually smaller. A more intuitive presentation of the idea is available in :cite:`cavanna15geometric`, and in a video :cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the -- cgit v1.2.3 From b6f3903f0ce07fe243ea7a3c18098043114f7f6a Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:52:27 +0000 Subject: epsilon + code block git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3939 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6a88d96a67d9d02f95e63fd627c295abebb49ce8 --- src/cython/doc/rips_complex_user.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index cddf4f16..933643e2 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -15,7 +15,7 @@ Definition | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -The `Rips complex `_ is a simplicial complex that generalizes proximity (ε-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. +The `Rips complex `_ is a simplicial complex that generalizes proximity (:math:`\varepsilon`-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. @@ -50,7 +50,7 @@ error is usually smaller. A more intuitive presentation of the idea is available in :cite:`cavanna15geometric`, and in a video :cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the construction of a `RipsComplex` object asks it to build a sparse Rips with -parameter `ε=0.3`, while the default `sparse=None` builds the +parameter :math:`\varepsilon=0.3`, while the default `sparse=None` builds the regular Rips complex. @@ -105,7 +105,13 @@ until dimension 1 - one skeleton graph in other words), the output is: [4, 6] -> 9.49 [3, 6] -> 11.00 -Notice that if we use `rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2)`, asking for very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. +Notice that if we use + +.. code-block:: python + + rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2) + +asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From e9d843d0a5c48315c45e8639e8bf9b79ccf904af Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:55:26 +0000 Subject: add example to the list of examples git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3940 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fe3c41785e3bb72766f7a817851583f82b9f7d15 --- src/cython/doc/examples.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'src/cython') diff --git a/src/cython/doc/examples.rst b/src/cython/doc/examples.rst index 1f02f8a2..edbc2f72 100644 --- a/src/cython/doc/examples.rst +++ b/src/cython/doc/examples.rst @@ -22,6 +22,7 @@ Examples * :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>` * :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>` * :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>` + * :download:`sparse_rips_persistence_diagram.py <../example/sparse_rips_persistence_diagram.py>` * :download:`random_cubical_complex_persistence_example.py <../example/random_cubical_complex_persistence_example.py>` * :download:`coordinate_graph_induced_complex.py <../example/coordinate_graph_induced_complex.py>` * :download:`functional_graph_induced_complex.py <../example/functional_graph_induced_complex.py>` -- cgit v1.2.3 From 665ba1dfe82b663ed755267b74c62706ec6eb88a Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 22:04:13 +0000 Subject: add myself as coauthor git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3941 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 61cf8acdce3bc5cb0c8261166e195eccc3f8bb54 --- src/cython/doc/rips_complex_sum.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_sum.inc b/src/cython/doc/rips_complex_sum.inc index 5616bfa9..ea26769a 100644 --- a/src/cython/doc/rips_complex_sum.inc +++ b/src/cython/doc/rips_complex_sum.inc @@ -1,6 +1,6 @@ -================================================================= =================================== =================================== -:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -================================================================= =================================== =================================== +===================================================================== =========================== =================================== +:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +===================================================================== =========================== =================================== +----------------------------------------------------------------+------------------------------------------------------------------------+ | .. figure:: | Rips complex is a simplicial complex constructed from a one skeleton | -- cgit v1.2.3 From 354da3ae06ffa2479d56e9ea45cefbe218da2c76 Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 22:11:23 +0000 Subject: Make RipsComplex a clickable link git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3942 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 642ae449f85cf8516fc632716ea14b22f74ec517 --- src/cython/doc/rips_complex_user.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 933643e2..e0c71cd1 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -19,7 +19,7 @@ The `Rips complex ` The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -When creating a simplicial complex from the graph, `RipsComplex` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. +When creating a simplicial complex from the graph, :doc:`RipsComplex ` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. A vertex name corresponds to the index of the point in the given range (aka. the point cloud). -- cgit v1.2.3 From 07c214f675595b75a2a9d1f8dc2888487aa6086a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 17 Oct 2018 08:11:14 +0000 Subject: Some indentation fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3960 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6dce53b98bc0b299a3621602f385b3b44e16d489 --- src/cython/doc/rips_complex_user.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index e0c71cd1..0aeffe55 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -69,7 +69,7 @@ Finally, it is asked to display information about the simplicial complex. import gudhi rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], - max_edge_length=12.0) + max_edge_length=12.0) simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ @@ -109,9 +109,11 @@ Notice that if we use .. code-block:: python - rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2) + rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], + max_edge_length=12.0, sparse=2) -asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. +asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), +2 to 5 edges disappear, depending on the random vertex used to start the sparsification. Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 4f07edab3e86ffe9f0bcd8c055592dff22fab2ce Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Oct 2018 19:30:14 +0000 Subject: Add persistence_dim_max argument in simplex tree persistence documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3963 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ef8f3b0c2b0e3cdbda73687f1e65877213918830 --- src/cython/cython/simplex_tree.pyx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx index 8397d9d9..0ab97f80 100644 --- a/src/cython/cython/simplex_tree.pyx +++ b/src/cython/cython/simplex_tree.pyx @@ -44,8 +44,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": void set_dimension(int dimension) int dimension() int upper_bound_dimension() - bint find_simplex(vector[int] simplex) - bint insert_simplex_and_subfaces(vector[int] simplex, + bool find_simplex(vector[int] simplex) + bool insert_simplex_and_subfaces(vector[int] simplex, double filtration) vector[pair[vector[int], double]] get_filtration() vector[pair[vector[int], double]] get_skeleton(int dimension) @@ -355,7 +355,7 @@ cdef class SimplexTree: :param filtration: Maximum threshold value. :type filtration: float. :returns: The filtration modification information. - :rtype: bint + :rtype: bool .. note:: @@ -406,7 +406,7 @@ cdef class SimplexTree: value than its faces by increasing the filtration values. :returns: The filtration modification information. - :rtype: bint + :rtype: bool .. note:: @@ -432,6 +432,10 @@ cdef class SimplexTree: 0.0. Sets 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 + ignored. Default is false. + :type persistence_dim_max: bool :returns: The persistence of the simplicial complex. :rtype: list of pairs(dimension, pair(birth, death)) """ -- cgit v1.2.3 From e8401b6fd2f9ff533824a6773f592b448d0863ed Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 31 Oct 2018 11:48:04 +0000 Subject: Make dependency with boost 1.56 instead of 1.48 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/boost_1.56_vincent@3967 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a5941b8c4f65ec8e6f62117aceb5f22e0142f255 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/common/doc/installation.h | 2 +- src/cython/doc/installation.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index b020ebfc..cde3725c 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -1,6 +1,6 @@ # This files manage third party libraries required by GUDHI -find_package(Boost 1.48.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) +find_package(Boost 1.56.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index df7eed37..bf2d0a87 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -5,7 +5,7 @@ * Examples of GUDHI headers inclusion can be found in \ref utilities. * * \section compiling Compiling - * The library uses c++11 and requires Boost ≥ 1.48.0 + * The library uses c++11 and requires Boost ≥ 1.56.0 * and CMake ≥ 3.1. * It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. * diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst index ef2f7af2..040f6b4a 100644 --- a/src/cython/doc/installation.rst +++ b/src/cython/doc/installation.rst @@ -7,7 +7,7 @@ Installation Compiling ********* -The library uses c++11 and requires `Boost `_ ≥ 1.48.0 +The library uses c++11 and requires `Boost `_ ≥ 1.56.0 and `CMake `_ ≥ 3.1. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. -- cgit v1.2.3 From e105da964b96218459c8822816de36273f6cdf17 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 17 Dec 2018 20:57:42 +0000 Subject: Merge tangential-miro branch Add reference to cubical in persistence module git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4038 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 832343cd6e2357c9e229d5b34f6de03e50d2da67 --- .../include/gudhi/Tangential_complex.h | 57 ++++++++++++++-------- src/cython/doc/persistent_cohomology_user.rst | 14 +++--- 2 files changed, 46 insertions(+), 25 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h index d1c846cf..37cdf1b4 100644 --- a/src/Tangential_complex/include/gudhi/Tangential_complex.h +++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -356,7 +357,7 @@ class Tangential_complex { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i); #ifdef GUDHI_USE_TBB } @@ -629,12 +630,12 @@ class Tangential_complex { // Don't export infinite cells if (!export_infinite_simplices && is_infinite(c)) continue; - if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; - if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex c.insert(idx); + if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; + // Try to insert the simplex bool inserted = tree.insert_simplex_and_subfaces(c).second; @@ -689,6 +690,10 @@ class Tangential_complex { // Don't export infinite cells if (!export_infinite_simplices && is_infinite(c)) continue; + if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); + // Add the missing center vertex + c.insert(idx); + if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; // Unusual simplex dim? @@ -701,10 +706,6 @@ class Tangential_complex { check_lower_and_higher_dim_simplices = 1; } - if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); - // Add the missing center vertex - c.insert(idx); - // Try to insert the simplex bool added = complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); @@ -800,7 +801,7 @@ class Tangential_complex { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i); #ifdef GUDHI_USE_TBB } @@ -835,7 +836,7 @@ class Tangential_complex { Refresh_tangent_triangulation(*this, updated_pts_ds)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) refresh_tangent_triangulation(i, updated_pts_ds); #ifdef GUDHI_USE_TBB } @@ -983,10 +984,9 @@ class Tangential_complex { // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin = boost::make_optional(false, FT()); - // This is the strange way boost is recommending to get rid of "may be used uninitialized in this function". - // Former code was : - // boost::optional squared_star_sphere_radius_plus_margin; + // If th the m_max_squared_edge_length is set the maximal radius of the "star sphere" + // is at most square root of m_max_squared_edge_length + boost::optional squared_star_sphere_radius_plus_margin = m_max_squared_edge_length; // Insert points until we find a point which is outside "star sphere" for (auto nn_it = ins_range.begin(); nn_it != ins_range.end(); ++nn_it) { @@ -999,10 +999,16 @@ class Tangential_complex { Point neighbor_pt; FT neighbor_weight; compute_perturbed_weighted_point(neighbor_point_idx, neighbor_pt, neighbor_weight); - + GUDHI_CHECK(!m_max_squared_edge_length || + squared_star_sphere_radius_plus_margin.value() <= m_max_squared_edge_length.value(), + std::invalid_argument("Tangential_complex::compute_star - set a bigger value with set_max_squared_edge_length.")); if (squared_star_sphere_radius_plus_margin && - k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin) + k_sqdist(center_pt, neighbor_pt) > squared_star_sphere_radius_plus_margin.value()) { + GUDHI_CHECK(triangulation.current_dimension() >= tangent_space_dim, + std::invalid_argument("Tangential_complex::compute_star - Dimension of the star is only " + \ + std::to_string(triangulation.current_dimension()))); break; + } Tr_point proj_pt = project_point_and_compute_weight(neighbor_pt, neighbor_weight, tsb, local_tr_traits); @@ -1044,7 +1050,7 @@ class Tangential_complex { FT sq_power_sphere_diam = 4 * point_weight(c); if (!squared_star_sphere_radius_plus_margin || - sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { + sq_power_sphere_diam > squared_star_sphere_radius_plus_margin.value()) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; } } @@ -1055,12 +1061,22 @@ class Tangential_complex { if (squared_star_sphere_radius_plus_margin) { // "2*m_last_max_perturb" because both points can be perturbed squared_star_sphere_radius_plus_margin = - CGAL::square(std::sqrt(*squared_star_sphere_radius_plus_margin) + 2 * m_last_max_perturb); + CGAL::square(std::sqrt(squared_star_sphere_radius_plus_margin.value()) + 2 * m_last_max_perturb); + + // Reduce the square radius to m_max_squared_edge_length if necessary + if (m_max_squared_edge_length && squared_star_sphere_radius_plus_margin.value() > m_max_squared_edge_length.value()) { + squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value(); + } // Save it in `m_squared_star_spheres_radii_incl_margin` - m_squared_star_spheres_radii_incl_margin[i] = *squared_star_sphere_radius_plus_margin; + m_squared_star_spheres_radii_incl_margin[i] = squared_star_sphere_radius_plus_margin.value(); } else { - m_squared_star_spheres_radii_incl_margin[i] = FT(-1); + if (m_max_squared_edge_length) { + squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value(); + m_squared_star_spheres_radii_incl_margin[i] = m_max_squared_edge_length.value(); + } else { + m_squared_star_spheres_radii_incl_margin[i] = FT(-1); + } } } } @@ -1968,6 +1984,8 @@ class Tangential_complex { return os; } + void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; } + private: const K m_k; const int m_intrinsic_dim; @@ -1993,6 +2011,7 @@ class Tangential_complex { // and their center vertex Stars_container m_stars; std::vector m_squared_star_spheres_radii_incl_margin; + boost::optional m_max_squared_edge_length; #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; diff --git a/src/cython/doc/persistent_cohomology_user.rst b/src/cython/doc/persistent_cohomology_user.rst index ce7fc685..de83cda1 100644 --- a/src/cython/doc/persistent_cohomology_user.rst +++ b/src/cython/doc/persistent_cohomology_user.rst @@ -10,12 +10,14 @@ Definition :Author: Clément Maria :Introduced in: GUDHI PYTHON 2.0.0 :Copyright: GPL v3 ===================================== ===================================== ===================================== -+---------------------------------------------+----------------------------------------------------------------------+ -| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | -| | feature for reference: | -| | | -| | * :doc:`simplex_tree_ref` | -+---------------------------------------------+----------------------------------------------------------------------+ ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and -- cgit v1.2.3 From f29a6e9a03dca95dc0a070b604fb11e18897a6f6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Feb 2019 14:08:56 +0000 Subject: Fix doc for C++ and Python. Fix some warnings on Nerve GIC sphinx doc generation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/cubical_complex_small_fix@4101 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 57eacb8c4108be212e61796c65e3b45bb9c13644 --- src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h | 13 +++++++------ src/common/doc/file_formats.h | 8 ++++---- src/cython/doc/cubical_complex_user.rst | 10 ++++++++-- src/cython/doc/fileformats.rst | 10 +++++++++- src/cython/doc/nerve_gic_complex_ref.rst | 4 ++++ src/cython/doc/nerve_gic_complex_user.rst | 4 ++++ 6 files changed, 36 insertions(+), 13 deletions(-) (limited to 'src/cython') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index e1e5885e..5fa02a5e 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -87,15 +87,16 @@ namespace cubical_complex { * * \section inputformat Input Format * - * In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star + * In the current implementation, filtration is given at the maximal cubes, and it is then extended by the lower star * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. * Currently one input from a text file is used. It uses a format inspired from the Perseus software - * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. Note however an important difference: while Perseus - * assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this and we allow any - * filtration values. - * As a consequence one cannot use -1's to indicate missing cubes. If you have missing cubes in your complex, please - * set their filtration to +Inf. The file format is described in details in here: \ref FileFormatsPerseus. + * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. + * \note While Perseus assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this + * and we allow any filtration values. As a consequence one cannot use `-1`'s to indicate missing cubes. If you have + * missing cubes in your complex, please set their filtration to \f$+\infty\f$ (aka. `inf` in the file). + * + * The file format is described in details in \ref FileFormatsPerseus file format section. * * \section PeriodicBoundaryConditions Periodic boundary conditions * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times diff --git a/src/common/doc/file_formats.h b/src/common/doc/file_formats.h index d38d90e0..23214e25 100644 --- a/src/common/doc/file_formats.h +++ b/src/common/doc/file_formats.h @@ -72,7 +72,7 @@ namespace Gudhi { \section FileFormatsPerseus Perseus - This file format is the format used by the Perseus software + This file format is a format inspired from the Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 @@ -119,9 +119,9 @@ namespace Gudhi { Other sample files can be found in the `data/bitmap` folder. - Please note that unlike in Perseus format the filtration on the maximal cubes can be any double precision number. - Consequently one cannot mark the cubes that are not present with -1's. To do that please set their filtration value to - +Inf. + \note Unlike in Perseus format the filtration on the maximal cubes can be any double precision number. + Consequently one cannot mark the cubes that are not present with `-1`'s. To do that please set their filtration value + to \f$+\infty\f$ (aka. `inf` in the file). */ } // namespace Gudhi diff --git a/src/cython/doc/cubical_complex_user.rst b/src/cython/doc/cubical_complex_user.rst index 320bd79b..19120360 100644 --- a/src/cython/doc/cubical_complex_user.rst +++ b/src/cython/doc/cubical_complex_user.rst @@ -83,9 +83,15 @@ Input Format. In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users who want to use the code directly. They can be found in the :doc:`cubical_complex_ref`. -Currently one input from a text file is used. It uses a format used already in +Currently one input from a text file is used. It uses a format inspired from the Perseus software `Perseus software `_ by Vidit Nanda. -The file format is described here: :doc:`Perseus `. + +.. note:: + While Perseus assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this and + we allow any filtration values. As a consequence one cannot use ``-1``'s to indicate missing cubes. If you have + missing cubes in your complex, please set their filtration to :math:`+\infty` (aka. ``inf`` in the file). + +The file format is described in details in :ref:`Perseus file format` file format section. .. testcode:: diff --git a/src/cython/doc/fileformats.rst b/src/cython/doc/fileformats.rst index ff20f26e..e205cc8b 100644 --- a/src/cython/doc/fileformats.rst +++ b/src/cython/doc/fileformats.rst @@ -51,10 +51,12 @@ Here is a simple sample file in the 3D case:: 1. 1. 1. +.. _Perseus file format: + Perseus ******* -This file format is the format used by the +This file format is a format inspired from the `Perseus software `_ by Vidit Nanda. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each @@ -88,3 +90,9 @@ Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. Other sample files can be found in the `data/bitmap` folder. + +.. note:: + Unlike in Perseus format the filtration on the maximal cubes can be any + double precision number. Consequently one cannot mark the cubes that are + not present with ``-1``'s. To do that please set their filtration value to + :math:`+\infty` (aka. ``inf`` in the file). \ No newline at end of file diff --git a/src/cython/doc/nerve_gic_complex_ref.rst b/src/cython/doc/nerve_gic_complex_ref.rst index e24e01fc..abde2e8c 100644 --- a/src/cython/doc/nerve_gic_complex_ref.rst +++ b/src/cython/doc/nerve_gic_complex_ref.rst @@ -1,3 +1,7 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + ================================ Cover complexes reference manual ================================ diff --git a/src/cython/doc/nerve_gic_complex_user.rst b/src/cython/doc/nerve_gic_complex_user.rst index d774827e..44f30e1a 100644 --- a/src/cython/doc/nerve_gic_complex_user.rst +++ b/src/cython/doc/nerve_gic_complex_user.rst @@ -1,3 +1,7 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + Cover complexes user manual =========================== Definition -- cgit v1.2.3 From 68c4ffe856b8de030bb4c7c75bccce7082d5478c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 14 Feb 2019 10:21:41 +0000 Subject: Fix https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/25 [python] A Cmake option to set/unset runtime_library_dirs cmake -DWITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS=OFF .. # to disable runtime_library_dirs set in setup.py cf. Debian disallows setting rpath, so I'm currently unsetting runtime_library_dirs for the Python extensions. Could this perhaps be made into a CMake option? https://git.nonempty.org/debian-gudhi/tree/debian/patches/0005-Don-t-set-runtime-library-dirs-for-Python-extensions.patch?h=debian/sid&id=fed62e52ab396f0d6ba9029f12d5ef35d7761989 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4105 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 75f19373b2f01c2757bf1b11c81beff64021ddd8 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 ++ src/cython/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index cde3725c..7b0d350d 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -154,6 +154,8 @@ if(NOT GUDHI_CYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_CYTHON_PATH is not valid.") endif(NOT GUDHI_CYTHON_PATH) +option(WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "Build with setting runtime_library_dirs. Usefull when setting rpath is not allowed" ON) + if(PYTHONINTERP_FOUND AND CYTHON_FOUND) # Default found version 2 if(PYTHON_VERSION_MAJOR EQUAL 2) diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index dc2e9278..97859c98 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -198,9 +198,9 @@ if(PYTHONINTERP_FOUND) set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") endif() - if(UNIX) + if(UNIX AND WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS) set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}") - endif(UNIX) + endif(UNIX AND WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS) # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) -- cgit v1.2.3 From d7216fffe2a7fb3b15dcb84a4d5464968ae4a436 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 14 Feb 2019 16:57:30 +0000 Subject: Fix https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/28 [python - install] make install does not install properly Use 'python setup.py install' command instead of copying files git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4108 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 652d3597897aa3e7d1df97083cc3e2e4ae14f090 --- src/cython/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 97859c98..480332d7 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -215,12 +215,7 @@ if(PYTHONINTERP_FOUND) add_custom_target(cython ALL DEPENDS gudhi.so COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") - # For installation purpose - # TODO(VR) : files matching pattern mechanism is copying all cython directory - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING - PATTERN "*.so" - PATTERN "*.dylib" - PATTERN "*.pyd") + install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py install)") # Test examples if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) -- cgit v1.2.3 From 6112bd15d73b00a07edd54eeaf9c94cdff93aa9e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 12 Mar 2019 23:12:51 +0100 Subject: Add some documentation for Fix #31 Cythonization of Fix #31 Add some tests --- .../include/gudhi/Tangential_complex.h | 13 +++++++++- .../test/test_tangential_complex.cpp | 30 ++++++++++++++++++++++ src/cython/cython/tangential_complex.pyx | 26 +++++++++++++++++++ src/cython/doc/tangential_complex_user.rst | 2 ++ ...complex_plain_homology_from_off_file_example.py | 1 + src/cython/include/Tangential_complex_interface.h | 15 +++++++---- src/cython/test/test_tangential_complex.py | 9 +++++++ 7 files changed, 90 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h index 37cdf1b4..4a78127c 100644 --- a/src/Tangential_complex/include/gudhi/Tangential_complex.h +++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h @@ -322,7 +322,11 @@ class Tangential_complex { for (std::size_t i = 0; i < m_points.size(); ++i) m_are_tangent_spaces_computed[i] = true; } - /// Computes the tangential complex. + /** \brief Computes the tangential complex. + * \exception std::invalid_argument In debug mode, if the computed star dimension is too low. Try to set a bigger + * maximal edge length value with `Tangential_complex::set_max_squared_edge_length` if + * this happens. + */ void compute_tangential_complex() { #ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS std::cerr << red << "WARNING: GUDHI_TC_PERFORM_EXTRA_CHECKS is defined. " @@ -1984,6 +1988,13 @@ class Tangential_complex { return os; } + /** \brief Sets the maximal possible squared edge length for the edges in the triangulations. + * + * @param[in] max_squared_edge_length Maximal possible squared edge length. + * + * If the maximal edge length value is too low `Tangential_complex::compute_tangential_complex` will throw an + * exception in debug mode. + */ void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; } private: diff --git a/src/Tangential_complex/test/test_tangential_complex.cpp b/src/Tangential_complex/test/test_tangential_complex.cpp index 4e2d4f65..103b8b30 100644 --- a/src/Tangential_complex/test/test_tangential_complex.cpp +++ b/src/Tangential_complex/test/test_tangential_complex.cpp @@ -126,3 +126,33 @@ BOOST_AUTO_TEST_CASE(test_mini_tangential) { BOOST_CHECK(stree.num_vertices() == 4); BOOST_CHECK(stree.num_simplices() == 6); } + +#ifdef GUDHI_DEBUG +BOOST_AUTO_TEST_CASE(test_basic_example_throw) { + typedef CGAL::Epick_d Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + typedef Kernel::Vector_d Vector; + typedef tc::Tangential_complex TC; + + const int INTRINSIC_DIM = 2; + const int AMBIENT_DIM = 3; + const int NUM_POINTS = 1000; + + Kernel k; + + // Generate points on a 2-sphere + CGAL::Random_points_on_sphere_d generator(AMBIENT_DIM, 3.); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0; i < NUM_POINTS; ++i) + points.push_back(*generator++); + + // Compute the TC + TC tc(points, INTRINSIC_DIM, k); + tc.set_max_squared_edge_length(0.01); + std::cout << "test_basic_example_throw - set_max_squared_edge_length(0.01) to make GUDHI_CHECK fail" << std::endl; + BOOST_CHECK_THROW(tc.compute_tangential_complex(), std::invalid_argument); + +} +#endif diff --git a/src/cython/cython/tangential_complex.pyx b/src/cython/cython/tangential_complex.pyx index 4bb07076..293ef8cb 100644 --- a/src/cython/cython/tangential_complex.pyx +++ b/src/cython/cython/tangential_complex.pyx @@ -36,6 +36,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": Tangential_complex_interface(int intrisic_dim, vector[vector[double]] points) # bool from_file is a workaround for cython to find the correct signature Tangential_complex_interface(int intrisic_dim, string off_file, bool from_file) + void compute_tangential_complex() except + vector[double] get_point(unsigned vertex) unsigned number_of_vertices() unsigned number_of_simplices() @@ -43,6 +44,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": unsigned number_of_inconsistent_stars() void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree) void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) + void set_max_squared_edge_length(double max_squared_edge_length) # TangentialComplex python interface cdef class TangentialComplex: @@ -92,6 +94,17 @@ cdef class TangentialComplex: """ return self.thisptr != NULL + def compute_tangential_complex(self): + """This function computes the tangential complex. + + Raises: + ValueError: In debug mode, if the computed star dimension is too + low. Try to set a bigger maximal edge length value with + :func:`~gudhi.Tangential_complex.set_max_squared_edge_length` + if this happens. + """ + self.thisptr.compute_tangential_complex() + def get_point(self, vertex): """This function returns the point corresponding to a given vertex. @@ -152,3 +165,16 @@ cdef class TangentialComplex: """ self.thisptr.fix_inconsistencies_using_perturbation(max_perturb, time_limit) + + def set_max_squared_edge_length(self, max_squared_edge_length): + """Sets the maximal possible squared edge length for the edges in the + triangulations. + + :param max_squared_edge_length: Maximal possible squared edge length. + :type max_squared_edge_length: double + + If the maximal edge length value is too low + :func:`~gudhi.Tangential_complex.compute_tangential_complex` + will throw an exception in debug mode. + """ + self.thisptr.set_max_squared_edge_length(max_squared_edge_length) diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 5ce69e86..97471baf 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -128,6 +128,7 @@ This example builds the Tangential complex of point set read in an OFF file. import gudhi tc = gudhi.TangentialComplex(intrisic_dim = 1, off_file=gudhi.__root_source_dir__ + '/data/points/alphacomplexdoc.off') + tc.compute_tangential_complex() result_str = 'Tangential contains ' + repr(tc.num_simplices()) + \ ' simplices - ' + repr(tc.num_vertices()) + ' vertices.' print(result_str) @@ -175,6 +176,7 @@ simplices. import gudhi tc = gudhi.TangentialComplex(intrisic_dim = 1, points=[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) + tc.compute_tangential_complex() result_str = 'Tangential contains ' + repr(tc.num_vertices()) + ' vertices.' print(result_str) diff --git a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py index 0f8f5e80..536517d1 100755 --- a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py +++ b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py @@ -50,6 +50,7 @@ with open(args.file, 'r') as f: print("TangentialComplex creation from points read in a OFF file") tc = gudhi.TangentialComplex(intrisic_dim = args.intrisic_dim, off_file=args.file) + tc.compute_tangential_complex() st = tc.create_simplex_tree() message = "Number of simplices=" + repr(st.num_simplices()) diff --git a/src/cython/include/Tangential_complex_interface.h b/src/cython/include/Tangential_complex_interface.h index 71418886..c4ddbdbe 100644 --- a/src/cython/include/Tangential_complex_interface.h +++ b/src/cython/include/Tangential_complex_interface.h @@ -49,8 +49,6 @@ class Tangential_complex_interface { Dynamic_kernel k; tangential_complex_ = new TC(points, intrisic_dim, k); - tangential_complex_->compute_tangential_complex(); - num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); } Tangential_complex_interface(int intrisic_dim, const std::string& off_file_name, bool from_file = true) { @@ -60,14 +58,17 @@ class Tangential_complex_interface { std::vector points = off_reader.get_point_cloud(); tangential_complex_ = new TC(points, intrisic_dim, k); - tangential_complex_->compute_tangential_complex(); - num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); } ~Tangential_complex_interface() { delete tangential_complex_; } + void compute_tangential_complex() { + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + std::vector get_point(unsigned vh) { std::vector vd; if (vh < tangential_complex_->number_of_vertices()) { @@ -104,7 +105,11 @@ class Tangential_complex_interface { simplex_tree->initialize_filtration(); } - private: + void set_max_squared_edge_length(double max_squared_edge_length) { + tangential_complex_->set_max_squared_edge_length(max_squared_edge_length); + } + +private: TC* tangential_complex_; TC::Num_inconsistencies num_inconsistencies_; }; diff --git a/src/cython/test/test_tangential_complex.py b/src/cython/test/test_tangential_complex.py index 5385a0d3..5c62f278 100755 --- a/src/cython/test/test_tangential_complex.py +++ b/src/cython/test/test_tangential_complex.py @@ -32,6 +32,15 @@ def test_tangential(): tc = TangentialComplex(intrisic_dim = 1, points=point_list) assert tc.__is_defined() == True assert tc.num_vertices() == 4 + assert tc.num_simplices() == 0 + assert tc.num_inconsistent_simplices() == 0 + assert tc.num_inconsistent_stars() == 0 + + tc.compute_tangential_complex() + assert tc.num_vertices() == 4 + assert tc.num_simplices() == 4 + assert tc.num_inconsistent_simplices() == 0 + assert tc.num_inconsistent_stars() == 0 st = tc.create_simplex_tree() assert st.__is_defined() == True -- cgit v1.2.3 From 481718886577973385f657484c124456890ffa76 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 13 Mar 2019 07:37:33 +0100 Subject: Improve documentation for Tangential complex (Fix #16) --- src/Tangential_complex/doc/Intro_tangential_complex.h | 5 +++-- src/cython/doc/tangential_complex_user.rst | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index f4fc8ac7..649ec389 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -46,9 +46,10 @@ An extensive description of the Tangential complex can be found in \cite tangent \subsection whatisthetc What is a Tangential Complex? Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$. -The input data is 4 points \f$ P \f$ located on a curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the figures. \f$ P \f$ located on a closed +curve embedded in 2D. \image html "tc_example_01.png" "The input" -For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ (e.g. using PCA). +For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$. \image html "tc_example_03.png" "The Voronoi diagram" diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 97471baf..5147797c 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -23,8 +23,9 @@ What is a Tangential Complex? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let us start with the description of the Tangential complex of a simple -example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points -:math:`P` located on a curve embedded in 2D. +example, with :math:`k = 1` and :math:`d = 2`. Only 4 points will be displayed +(more are required for PCA) to simplify the figures. :math:`P` located +on a closed curve embedded in 2D. .. figure:: ../../doc/Tangential_complex/tc_example_01.png :alt: The input @@ -32,8 +33,7 @@ example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points The input -For each point :math:`p`, estimate its tangent subspace :math:`T_p` (e.g. -using PCA). +For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals -- cgit v1.2.3 From 3ec4014f39c514aa456a652bc0d876fba70ad6f9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 14 Mar 2019 18:05:11 +0100 Subject: Fix code review --- src/Tangential_complex/doc/Intro_tangential_complex.h | 19 +++++++++++-------- src/cython/doc/tangential_complex_user.rst | 13 +++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index 649ec389..2b019021 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -35,9 +35,11 @@ namespace tangential_complex { \section tangentialdefinition Definition -A Tangential Delaunay complex is a simplicial complex +A Tangential Delaunay complex is a +simplicial complex designed to reconstruct a \f$k\f$-dimensional smooth manifold embedded in \f$d\f$-dimensional Euclidean space. -The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of "small" intrinsic dimension. +The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of +"small" intrinsic dimension. The running time depends only linearly on the extrinsic dimension \f$ d \f$ and exponentially on the intrinsic dimension \f$ k \f$. @@ -46,18 +48,19 @@ An extensive description of the Tangential complex can be found in \cite tangent \subsection whatisthetc What is a Tangential Complex? Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$. -Only 4 points will be displayed (more are required for PCA) to simplify the figures. \f$ P \f$ located on a closed -curve embedded in 2D. +The point set \f$ \mathscr P \f$ is located on a closed curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the figures. \image html "tc_example_01.png" "The input" -For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. +For each point \f$ P \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" -Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$. +Let us add the Voronoi diagram of the points in orange. For each point \f$ P \f$, construct its star in the Delaunay +triangulation of \f$ \mathscr P \f$ restricted to \f$ T_p \f$. \image html "tc_example_03.png" "The Voronoi diagram" The Tangential Delaunay complex is the union of those stars. In practice, neither the ambient Voronoi diagram nor the ambient Delaunay triangulation is computed. -Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only need the star of each point. -More details can be found in \cite tangentialcomplex2014. +Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only +need the star of each point. More details can be found in \cite tangentialcomplex2014. \subsection inconsistencies Inconsistencies diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 5147797c..11b37009 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -23,9 +23,10 @@ What is a Tangential Complex? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let us start with the description of the Tangential complex of a simple -example, with :math:`k = 1` and :math:`d = 2`. Only 4 points will be displayed -(more are required for PCA) to simplify the figures. :math:`P` located -on a closed curve embedded in 2D. +example, with :math:`k = 1` and :math:`d = 2`. The point set +:math:`\mathscr P` is located on a closed curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the +figures. .. figure:: ../../doc/Tangential_complex/tc_example_01.png :alt: The input @@ -33,7 +34,7 @@ on a closed curve embedded in 2D. The input -For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. +For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals @@ -43,8 +44,8 @@ For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. Let us add the Voronoi diagram of the points in orange. For each point -:math:`p`, construct its star in the Delaunay triangulation of :math:`P` -restricted to :math:`T_p`. +:math:`P`, construct its star in the Delaunay triangulation of +:math:`\mathscr P` restricted to :math:`T_p`. .. figure:: ../../doc/Tangential_complex/tc_example_03.png :alt: The Voronoi diagram -- cgit v1.2.3 From fe79987e03b5bce4515638f8d0549ae8db64f3e6 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 15 Mar 2019 08:32:37 +0100 Subject: Fix code review --- src/Tangential_complex/doc/Intro_tangential_complex.h | 6 +++--- src/cython/doc/tangential_complex_user.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index 2b019021..501f4a8b 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -51,10 +51,10 @@ Let us start with the description of the Tangential complex of a simple example, The point set \f$ \mathscr P \f$ is located on a closed curve embedded in 2D. Only 4 points will be displayed (more are required for PCA) to simplify the figures. \image html "tc_example_01.png" "The input" -For each point \f$ P \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. +For each point \f$ P \f$, estimate its tangent subspace \f$ T_P \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" Let us add the Voronoi diagram of the points in orange. For each point \f$ P \f$, construct its star in the Delaunay -triangulation of \f$ \mathscr P \f$ restricted to \f$ T_p \f$. +triangulation of \f$ \mathscr P \f$ restricted to \f$ T_P \f$. \image html "tc_example_03.png" "The Voronoi diagram" The Tangential Delaunay complex is the union of those stars. @@ -69,7 +69,7 @@ An inconsistency occurs when a simplex is not in the star of all its vertices. Let us take the same example. \image html "tc_example_07_before.png" "Before" -Let us slightly move the tangent subspace \f$ T_q \f$ +Let us slightly move the tangent subspace \f$ T_Q \f$ \image html "tc_example_07_after.png" "After" Now, the star of \f$ Q \f$ contains \f$ QP \f$, but the star of \f$ P \f$ does not contain \f$ QP \f$. We have an inconsistency. \image html "tc_example_08.png" "After" diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 11b37009..ebfe1e29 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -34,7 +34,7 @@ figures. The input -For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. +For each point :math:`P`, estimate its tangent subspace :math:`T_P` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals @@ -45,7 +45,7 @@ For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. Let us add the Voronoi diagram of the points in orange. For each point :math:`P`, construct its star in the Delaunay triangulation of -:math:`\mathscr P` restricted to :math:`T_p`. +:math:`\mathscr P` restricted to :math:`T_P`. .. figure:: ../../doc/Tangential_complex/tc_example_03.png :alt: The Voronoi diagram @@ -73,7 +73,7 @@ Let us take the same example. Before -Let us slightly move the tangent subspace :math:`T_q` +Let us slightly move the tangent subspace :math:`T_Q` .. figure:: ../../doc/Tangential_complex/tc_example_07_after.png :alt: After -- cgit v1.2.3 From b2675aa4e27dd19ecf8bcef18a53f380d8a21421 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 15 Mar 2019 16:36:53 +0100 Subject: Improve python installation documentation --- src/cython/doc/installation.rst | 56 +++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst index 040f6b4a..855dea44 100644 --- a/src/cython/doc/installation.rst +++ b/src/cython/doc/installation.rst @@ -7,24 +7,23 @@ Installation Compiling ********* -The library uses c++11 and requires `Boost `_ ≥ 1.56.0 -and `CMake `_ ≥ 3.1. +The library uses c++11 and requires `Boost `_ ≥ 1.56.0, +`CMake `_ ≥ 3.1 to generate makefiles, and +`Cython `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. -It also requires cmake to generate makefiles, and cython to compile the -library. On `Windows `_ , only Python 3.5 and 3.6 are available because of the required Visual Studio version. -On other systems, if you have several Python/cython installed, the version 2.X +On other systems, if you have several Python/Cython installed, the version 2.X will be used by default, but you can force it by adding :code:`-DPython_ADDITIONAL_VERSIONS=3` to the cmake command. -GUDHI Cythonization -=================== +GUDHI Python module compilation +=============================== -To build the GUDHI cython module, run the following commands in a terminal: +To build the GUDHI Python module, run the following commands in a terminal: .. code-block:: bash @@ -32,7 +31,28 @@ To build the GUDHI cython module, run the following commands in a terminal: mkdir build cd build/ cmake .. - make cython + cd cython + make + +GUDHI Python module installation +================================ + +Once the compilation succeeds, one can add the GUDHI Python module path to the +PYTHONPATH: + +.. code-block:: bash + + # For windows, you have to set PYTHONPATH environment variable + export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython' + +Or install it definitely in your Python packages folder: + +.. code-block:: bash + + cd /path-to-gudhi/build/cython + # May require sudo or administrator privileges + make install + Test suites =========== @@ -45,7 +65,7 @@ following command in a terminal: cd /path-to-gudhi/build/cython # For windows, you have to set PYTHONPATH environment variable export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython' - ctest -R py_test + make test Debugging issues ================ @@ -54,7 +74,7 @@ If tests fail, please check your PYTHONPATH and try to :code:`import gudhi` and check the errors. The problem can come from a third-party library bad link or installation. -If :code:`import gudhi` succeeds, please have a look to debug informations: +If :code:`import gudhi` succeeds, please have a look to debug information: .. code-block:: python @@ -105,13 +125,17 @@ A complete configuration would be : Documentation ============= -To build the documentation, `sphinx-doc `_ is -required. Please refer to *conf.py* file to see which -`sphinx-doc `_ modules are required to -generate the documentation. Run the following commands in a terminal: +To build the documentation, `sphinx-doc `_ and +`sphinxcontrib-bibtex `_ are +required. As the documentation is auto-tested, `CGAL`_, `Eigen3`_, +`Matplotlib`_, `NumPy`_ and `SciPy`_ are also mandatory to build the +documentation. + +Run the following commands in a terminal: .. code-block:: bash + cd /path-to-gudhi/build/cython make sphinx Optional third-party library @@ -127,7 +151,7 @@ The :doc:`Alpha complex `, C++ library which provides easy access to efficient and reliable geometric algorithms. -Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or +Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or higher installed is recommended. The procedure to install this library according to your operating system is detailed `here `_. -- cgit v1.2.3 From 6525c78704489b0c8cb62b2e3f882ce6113c0f0d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 16 Apr 2019 23:19:19 +0200 Subject: Add min and max filtration values for the sparse Rips --- src/Rips_complex/doc/Intro_rips_complex.h | 11 +++++---- .../include/gudhi/Sparse_rips_complex.h | 27 ++++++++++++++-------- src/cython/doc/rips_complex_user.rst | 4 ++-- src/cython/include/Rips_complex_interface.h | 13 +++-------- 4 files changed, 30 insertions(+), 25 deletions(-) (limited to 'src/cython') diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 1aac804b..1d8cd2ba 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -99,10 +99,13 @@ namespace rips_complex { * \cite cavanna15geometric, and in a video \cite cavanna15visualizing. * * The interface of `Sparse_rips_complex` is similar to the one for the usual - * `Rips_complex`, except that one has to specify the approximation factor, and - * there is no option to limit the maximum filtration value (the way the - * approximation is done means that larger filtration values are much cheaper - * to handle than low filtration values, so the gain would be too small). + * `Rips_complex`, except that one has to specify the approximation factor. + * There is an option to limit the minimum and maximum filtration values, but + * they are not recommended: the way the approximation is done means that + * larger filtration values are much cheaper to handle than low filtration + * values, so the gain in ignoring the large ones is small, and + * `Gudhi::subsampling::sparsify_point_set()` is a more efficient way of + * ignoring small filtration values. * * Theoretical guarantees are only available for \f$\epsilon<1\f$. The * construction accepts larger values of ε, and the size of the complex diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index 1e8fb6a3..a249cd8e 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -70,17 +70,19 @@ class Sparse_rips_complex { * @param[in] points Range of points. * @param[in] distance Distance function that returns a `Filtration_value` from 2 given points. * @param[in] epsilon Approximation parameter. epsilon must be positive. + * @param[in] mini Minimal filtration value. Ignore anything below this scale. This is a less efficient version of `Gudhi::subsampling::sparsify_point_set()`. + * @param[in] maxi Maximal filtration value. Ignore anything above this scale. * */ template - Sparse_rips_complex(const RandomAccessPointRange& points, Distance distance, double epsilon) + Sparse_rips_complex(const RandomAccessPointRange& points, Distance distance, double epsilon, Filtration_value mini=-std::numeric_limits::infinity(), Filtration_value maxi=std::numeric_limits::infinity()) : epsilon_(epsilon) { GUDHI_CHECK(epsilon > 0, "epsilon must be positive"); auto dist_fun = [&](Vertex_handle i, Vertex_handle j) { return distance(points[i], points[j]); }; Ker kernel(dist_fun); subsampling::choose_n_farthest_points(kernel, boost::irange(0, boost::size(points)), -1, -1, std::back_inserter(sorted_points), std::back_inserter(params)); - compute_sparse_graph(dist_fun, epsilon); + compute_sparse_graph(dist_fun, epsilon, mini, maxi); } /** \brief Sparse_rips_complex constructor from a distance matrix. @@ -90,11 +92,14 @@ class Sparse_rips_complex { * \f$j\f$ as long as \f$ 0 \leqslant j < i \leqslant * distance\_matrix.size().\f$ * @param[in] epsilon Approximation parameter. epsilon must be positive. + * @param[in] mini Minimal filtration value. Ignore anything below this scale. This is a less efficient version of `Gudhi::subsampling::sparsify_point_set()`. + * @param[in] maxi Maximal filtration value. Ignore anything above this scale. */ template - Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon) + Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon, Filtration_value mini=-std::numeric_limits::infinity(), Filtration_value maxi=std::numeric_limits::infinity()) : Sparse_rips_complex(boost::irange(0, boost::size(distance_matrix)), - [&](Vertex_handle i, Vertex_handle j) { return (i==j) ? 0 : (i - void compute_sparse_graph(Distance& dist, double epsilon) { + void compute_sparse_graph(Distance& dist, double epsilon, Filtration_value mini, Filtration_value maxi) { const auto& points = sorted_points; // convenience alias const int n = boost::size(points); graph_.~Graph(); @@ -164,13 +169,15 @@ class Sparse_rips_complex { // TODO(MG): // - make it parallel // - only test near-enough neighbors - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { + auto&& pi = points[i]; + auto li = params[i]; + if (li < mini) break; for (int j = i + 1; j < n; ++j) { - auto&& pi = points[i]; auto&& pj = points[j]; auto d = dist(pi, pj); - auto li = params[i]; auto lj = params[j]; + if (lj < mini) break; GUDHI_CHECK(lj <= li, "Bad furthest point sorting"); Filtration_value alpha; @@ -182,8 +189,10 @@ class Sparse_rips_complex { else continue; - add_edge(pi, pj, alpha, graph_); + if (alpha <= maxi) + add_edge(pi, pj, alpha, graph_); } + } } Graph graph_; diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index e814b4c3..1d340dbe 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -50,8 +50,8 @@ by more than the length used to define "too close". A more general technique is to use a sparse approximation of the Rips introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version described in :cite:`buchet16efficient` (except that we multiply all filtration -values by 2, to match the usual Rips complex), which proves a -:math:`\frac{1+\varepsilon}{1-\varepsilon}`-interleaving, although in practice the +values by 2, to match the usual Rips complex). :cite:`cavanna15geometric` proves +a :math:`\frac{1}{1-\varepsilon}`-interleaving, although in practice the error is usually smaller. A more intuitive presentation of the idea is available in :cite:`cavanna15geometric`, and in a video :cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h index 1a6e2477..40aff299 100644 --- a/src/cython/include/Rips_complex_interface.h +++ b/src/cython/include/Rips_complex_interface.h @@ -54,23 +54,17 @@ class Rips_complex_interface { } void init_points_sparse(const std::vector>& points, double threshold, double epsilon) { - sparse_rips_complex_.emplace(points, Gudhi::Euclidean_distance(), epsilon); - threshold_ = threshold; + sparse_rips_complex_.emplace(points, Gudhi::Euclidean_distance(), epsilon, -std::numeric_limits::infinity(), threshold); } void init_matrix_sparse(const std::vector>& matrix, double threshold, double epsilon) { - sparse_rips_complex_.emplace(matrix, epsilon); - threshold_ = threshold; + sparse_rips_complex_.emplace(matrix, epsilon, -std::numeric_limits::infinity(), threshold); } void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, int dim_max) { if (rips_complex_) rips_complex_->create_complex(*simplex_tree, dim_max); - else { + else sparse_rips_complex_->create_complex(*simplex_tree, dim_max); - // This pruning should be done much earlier! It isn't that useful for sparse Rips, - // but it would be inconsistent not to do it. - simplex_tree->prune_above_filtration(threshold_); - } simplex_tree->initialize_filtration(); } @@ -79,7 +73,6 @@ class Rips_complex_interface { // Anyway, storing a graph would make more sense. Or changing the interface completely so there is no such storage. boost::optional::Filtration_value>> rips_complex_; boost::optional::Filtration_value>> sparse_rips_complex_; - double threshold_; }; } // namespace rips_complex -- cgit v1.2.3 From 27114ca8df752b4ddd24f0ebf161f46882e352df Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 10 May 2019 12:37:48 +0200 Subject: Clarify doc of witness complex --- .../example/example_nearest_landmark_table.cpp | 21 +++++++++------------ .../include/gudhi/Strong_witness_complex.h | 4 ++-- src/Witness_complex/include/gudhi/Witness_complex.h | 8 ++++---- src/cython/cython/strong_witness_complex.pyx | 10 +++++----- src/cython/cython/witness_complex.pyx | 10 +++++----- .../witness_complex_from_nearest_landmark_table.py | 12 ++++++------ 6 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src/cython') diff --git a/src/Witness_complex/example/example_nearest_landmark_table.cpp b/src/Witness_complex/example/example_nearest_landmark_table.cpp index acaf7c54..441900c1 100644 --- a/src/Witness_complex/example/example_nearest_landmark_table.cpp +++ b/src/Witness_complex/example/example_nearest_landmark_table.cpp @@ -19,22 +19,19 @@ int main(int argc, char * const argv[]) { using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology; Simplex_tree simplex_tree; - Nearest_landmark_table nlt; // Example contains 5 witnesses and 5 landmarks - Nearest_landmark_range w0 = {std::make_pair(0, 0), std::make_pair(1, 1), std::make_pair(2, 2), - std::make_pair(3, 3), std::make_pair(4, 4)}; nlt.push_back(w0); - Nearest_landmark_range w1 = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(3, 2), - std::make_pair(4, 3), std::make_pair(0, 4)}; nlt.push_back(w1); - Nearest_landmark_range w2 = {std::make_pair(2, 0), std::make_pair(3, 1), std::make_pair(4, 2), - std::make_pair(0, 3), std::make_pair(1, 4)}; nlt.push_back(w2); - Nearest_landmark_range w3 = {std::make_pair(3, 0), std::make_pair(4, 1), std::make_pair(0, 2), - std::make_pair(1, 3), std::make_pair(2, 4)}; nlt.push_back(w3); - Nearest_landmark_range w4 = {std::make_pair(4, 0), std::make_pair(0, 1), std::make_pair(1, 2), - std::make_pair(2, 3), std::make_pair(3, 4)}; nlt.push_back(w4); + Nearest_landmark_table nlt = { + {{0, 0.0}, {1, 0.1}, {2, 0.2}, {3, 0.3}, {4, 0.4}}, // witness 0 + {{1, 0.0}, {2, 0.1}, {3, 0.2}, {4, 0.3}, {0, 0.4}}, // witness 1 + {{2, 0.0}, {3, 0.1}, {4, 0.2}, {0, 0.3}, {1, 0.4}}, // witness 2 + {{3, 0.0}, {4, 0.1}, {0, 0.2}, {1, 0.3}, {2, 0.4}}, // witness 3 + {{4, 0.0}, {0, 0.1}, {1, 0.2}, {2, 0.3}, {3, 0.4}} // witness 4 + }; + /* distance(witness3, landmark3) is 0, distance(witness3, landmark4) is 0.1, etc. */ Witness_complex witness_complex(nlt); - witness_complex.create_complex(simplex_tree, 4.1); + witness_complex.create_complex(simplex_tree, .41); std::cout << "Number of simplices: " << simplex_tree.num_simplices() << std::endl; diff --git a/src/Witness_complex/include/gudhi/Strong_witness_complex.h b/src/Witness_complex/include/gudhi/Strong_witness_complex.h index fd6b3f38..5fd116b9 100644 --- a/src/Witness_complex/include/gudhi/Strong_witness_complex.h +++ b/src/Witness_complex/include/gudhi/Strong_witness_complex.h @@ -40,10 +40,10 @@ namespace witness_complex { * \brief Constructs strong witness complex for a given table of nearest landmarks with respect to witnesses. * \ingroup witness_complex * - * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances. + * \tparam Nearest_landmark_table_ needs to be a range (one entry per witness) of sorted ranges of pairs of nearest landmarks and distances. * The class Nearest_landmark_table_::value_type must be a copiable range. * The range of pairs must admit a member type 'iterator'. The dereference type - * of the pair range iterator needs to be 'std::pair'. + * of the pair range iterator needs to be 'std::pair' where the first element is the index of the landmark, and the second its (squared) distance to the witness. */ template< class Nearest_landmark_table_ > class Strong_witness_complex { diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 67885258..4063e040 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -75,10 +75,10 @@ class Witness_complex { /** * \brief Initializes member variables before constructing simplicial complex. * \details Records nearest landmark table. - * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances. + * @param[in] nearest_landmark_table needs to be a range (one entry per witness) of sorted ranges of pairs of nearest landmarks and distances. * The class Nearest_landmark_table_::value_type must be a copiable range. * The range of pairs must admit a member type 'iterator'. The dereference type - * of the pair range iterator needs to be 'std::pair'. + * of the pair range iterator needs to be 'std::pair' where the first element is the index of the landmark, and the second its (squared) distance to the witness. */ Witness_complex(Nearest_landmark_table_ const & nearest_landmark_table) @@ -108,8 +108,8 @@ class Witness_complex { } ActiveWitnessList active_witnesses; Landmark_id k = 0; /* current dimension in iterative construction */ - for (auto w : nearest_landmark_table_) - active_witnesses.push_back(ActiveWitness(w)); + for (auto&& w : nearest_landmark_table_) + active_witnesses.emplace_back(w); while (!active_witnesses.empty() && k <= limit_dimension) { typename ActiveWitnessList::iterator aw_it = active_witnesses.begin(); std::vector simplex; diff --git a/src/cython/cython/strong_witness_complex.pyx b/src/cython/cython/strong_witness_complex.pyx index 74c5cb05..1da2466f 100644 --- a/src/cython/cython/strong_witness_complex.pyx +++ b/src/cython/cython/strong_witness_complex.pyx @@ -47,8 +47,8 @@ cdef class StrongWitnessComplex: def __init__(self, nearest_landmark_table=None): """StrongWitnessComplex constructor. - :param nearest_landmark_table: A list of nearest landmark. - :type nearest_landmark_table: list of list of pair of unsigned and double + :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to witness w, and d is the (squared) distance between l and w. + :type nearest_landmark_table: list of list of pair of int and float """ # The real cython constructor @@ -65,10 +65,10 @@ cdef class StrongWitnessComplex: """ return self.thisptr != NULL - def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + def create_simplex_tree(self, max_alpha_square = float('inf'), limit_dimension = -1): """ - :param max_alpha_square: The maximum alpha square threshold the - simplices shall not exceed. Default is set to infinity. + :param max_alpha_square: The maximum relaxation parameter. + Default is set to infinity. :type max_alpha_square: float :returns: A simplex tree created from the Delaunay Triangulation. :rtype: SimplexTree diff --git a/src/cython/cython/witness_complex.pyx b/src/cython/cython/witness_complex.pyx index 8591465a..d230fd49 100644 --- a/src/cython/cython/witness_complex.pyx +++ b/src/cython/cython/witness_complex.pyx @@ -47,8 +47,8 @@ cdef class WitnessComplex: def __init__(self, nearest_landmark_table=None): """WitnessComplex constructor. - :param nearest_landmark_table: A list of nearest landmark. - :type nearest_landmark_table: list of list of pair of unsigned and double + :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to witness w, and d is the (squared) distance between l and w. + :type nearest_landmark_table: list of list of pair of int and float """ # The real cython constructor @@ -65,10 +65,10 @@ cdef class WitnessComplex: """ return self.thisptr != NULL - def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + def create_simplex_tree(self, max_alpha_square = float('inf'), limit_dimension = -1): """ - :param max_alpha_square: The maximum alpha square threshold the - simplices shall not exceed. Default is set to infinity. + :param max_alpha_square: The maximum relaxation parameter. + Default is set to infinity. :type max_alpha_square: float :returns: A simplex tree created from the Delaunay Triangulation. :rtype: SimplexTree diff --git a/src/cython/example/witness_complex_from_nearest_landmark_table.py b/src/cython/example/witness_complex_from_nearest_landmark_table.py index e6b295ee..1b79d9b2 100755 --- a/src/cython/example/witness_complex_from_nearest_landmark_table.py +++ b/src/cython/example/witness_complex_from_nearest_landmark_table.py @@ -30,14 +30,14 @@ __license__ = "GPL v3" print("#####################################################################") print("WitnessComplex creation from nearest landmark table") -nearest_landmark_table = [[[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]], - [[1, 0], [2, 1], [3, 2], [4, 3], [0, 4]], - [[2, 0], [3, 1], [4, 2], [0, 3], [1, 4]], - [[3, 0], [4, 1], [0, 2], [1, 3], [2, 4]], - [[4, 0], [0, 1], [1, 2], [2, 3], [3, 4]]] +nearest_landmark_table = [[[0, 0.0], [1, 0.1], [2, 0.2], [3, 0.3], [4, 0.4]], + [[1, 0.0], [2, 0.1], [3, 0.2], [4, 0.3], [0, 0.4]], + [[2, 0.0], [3, 0.1], [4, 0.2], [0, 0.3], [1, 0.4]], + [[3, 0.0], [4, 0.1], [0, 0.2], [1, 0.3], [2, 0.4]], + [[4, 0.0], [0, 0.1], [1, 0.2], [2, 0.3], [3, 0.4]]] witness_complex = StrongWitnessComplex(nearest_landmark_table=nearest_landmark_table) -simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=4.1) +simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=0.41) message = "Number of simplices: " + repr(simplex_tree.num_simplices()) print(message) -- cgit v1.2.3 From a858e7001808a20c7335593e1b056dfc546ed206 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 27 May 2019 12:00:45 +0200 Subject: long lines --- src/cython/cython/strong_witness_complex.pyx | 4 +++- src/cython/cython/witness_complex.pyx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/strong_witness_complex.pyx b/src/cython/cython/strong_witness_complex.pyx index 1da2466f..4b7bff34 100644 --- a/src/cython/cython/strong_witness_complex.pyx +++ b/src/cython/cython/strong_witness_complex.pyx @@ -47,7 +47,9 @@ cdef class StrongWitnessComplex: def __init__(self, nearest_landmark_table=None): """StrongWitnessComplex constructor. - :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to witness w, and d is the (squared) distance between l and w. + :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. + `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to + witness w, and d is the (squared) distance between l and w. :type nearest_landmark_table: list of list of pair of int and float """ diff --git a/src/cython/cython/witness_complex.pyx b/src/cython/cython/witness_complex.pyx index d230fd49..b1cce83f 100644 --- a/src/cython/cython/witness_complex.pyx +++ b/src/cython/cython/witness_complex.pyx @@ -47,7 +47,9 @@ cdef class WitnessComplex: def __init__(self, nearest_landmark_table=None): """WitnessComplex constructor. - :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to witness w, and d is the (squared) distance between l and w. + :param nearest_landmark_table: A list of lists of nearest landmarks and their distances. + `nearest_landmark_table[w][k]==(l,d)` means that l is the k-th nearest landmark to + witness w, and d is the (squared) distance between l and w. :type nearest_landmark_table: list of list of pair of int and float """ -- cgit v1.2.3