From 0a071114ad08d2ce149f8b484dd8ff1b96b61fb1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 9 Nov 2020 22:55:00 +0100 Subject: Don't test the equality case in sparsify_point_set. sqrt. --- src/python/test/test_subsampling.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/python/test') diff --git a/src/python/test/test_subsampling.py b/src/python/test/test_subsampling.py index 31f64e32..4019852e 100755 --- a/src/python/test/test_subsampling.py +++ b/src/python/test/test_subsampling.py @@ -141,12 +141,16 @@ def test_simple_sparsify_points(): # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 0.0) == [] # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 10.0) == [] assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=0.0) == point_set - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.0) == point_set - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.0) == [ + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=0.999) == point_set + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.001) == [ [0, 1], [1, 0], ] - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.01) == [[0, 1]] + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.999) == [ + [0, 1], + [1, 0], + ] + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.001) == [[0, 1]] assert ( len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=0.0)) @@ -157,11 +161,11 @@ def test_simple_sparsify_points(): == 5 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=40.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=40.1)) == 4 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=90.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=89.9)) == 3 ) assert ( @@ -169,7 +173,7 @@ def test_simple_sparsify_points(): == 2 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=325.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=324.9)) == 2 ) assert ( -- cgit v1.2.3 From 55e2b2e55bc50a7cfea9ca1edfca632488cf016a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 15:49:43 +0100 Subject: Make representations tests work if CGAL and/or POT is not there --- .../diagram_vectorizations_distances_kernels.py | 19 +++++++++++++------ src/python/test/test_representations.py | 10 +++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src/python/test') diff --git a/src/python/example/diagram_vectorizations_distances_kernels.py b/src/python/example/diagram_vectorizations_distances_kernels.py index c4a71a7a..2801576e 100755 --- a/src/python/example/diagram_vectorizations_distances_kernels.py +++ b/src/python/example/diagram_vectorizations_distances_kernels.py @@ -5,11 +5,11 @@ import numpy as np from sklearn.kernel_approximation import RBFSampler from sklearn.preprocessing import MinMaxScaler -from gudhi.representations import DiagramSelector, Clamping, Landscape, Silhouette, BettiCurve, ComplexPolynomial,\ +from gudhi.representations import (DiagramSelector, Clamping, Landscape, Silhouette, BettiCurve, ComplexPolynomial,\ TopologicalVector, DiagramScaler, BirthPersistenceTransform,\ PersistenceImage, PersistenceWeightedGaussianKernel, Entropy, \ PersistenceScaleSpaceKernel, SlicedWassersteinDistance,\ - SlicedWassersteinKernel, BottleneckDistance, PersistenceFisherKernel, WassersteinDistance + SlicedWassersteinKernel, PersistenceFisherKernel, WassersteinDistance) D1 = np.array([[0.,4.],[1.,2.],[3.,8.],[6.,8.], [0., np.inf], [5., np.inf]]) @@ -93,14 +93,21 @@ print("SW distance is " + str(sW(D1, D2))) SW = SlicedWassersteinKernel(num_directions=100, bandwidth=1.) print("SW kernel is " + str(SW(D1, D2))) -W = WassersteinDistance(order=2, internal_p=2, mode="pot") -print("Wasserstein distance (POT) is " + str(W(D1, D2))) +try: + W = WassersteinDistance(order=2, internal_p=2, mode="pot") + print("Wasserstein distance (POT) is " + str(W(D1, D2))) +except ImportError: + print("WassersteinDistance (POT) is not available, you may be missing pot.") W = WassersteinDistance(order=2, internal_p=2, mode="hera", delta=0.0001) print("Wasserstein distance (hera) is " + str(W(D1, D2))) -W = BottleneckDistance(epsilon=.001) -print("Bottleneck distance is " + str(W(D1, D2))) +try: + from gudhi.representations import BottleneckDistance + W = BottleneckDistance(epsilon=.001) + print("Bottleneck distance is " + str(W(D1, D2))) +except ImportError: + print("BottleneckDistance is not available, you may be missing CGAL.") PF = PersistenceFisherKernel(bandwidth_fisher=1., bandwidth=1.) print("PF kernel is " + str(PF(D1, D2))) diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 43c914f3..8ebd7888 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -41,7 +41,15 @@ def test_multiple(): assert d1 == pytest.approx(d2) assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) d1 = pairwise_persistence_diagram_distances(l1, l2, metric="wasserstein", order=2, internal_p=2) - d2 = WassersteinDistance(order=2, internal_p=2, n_jobs=4).fit(l2).transform(l1) + mode = "" + try: + import ot + mode = "pot" + except ImportError: + print("POT is not available, try with hera") + mode = "hera" + + d2 = WassersteinDistance(order=2, internal_p=2, mode=mode, n_jobs=4).fit(l2).transform(l1) print(d1.shape, d2.shape) assert d1 == pytest.approx(d2, rel=0.02) -- cgit v1.2.3 From 366813c651d871c5b95d9bc8e7ea227f8015fc55 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 16:35:48 +0100 Subject: rollback test_representation and a CGAL condition to launch it --- src/python/CMakeLists.txt | 2 +- src/python/test/test_representations.py | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'src/python/test') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 56b6876c..4dca3908 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -504,7 +504,7 @@ if(PYTHONINTERP_FOUND) endif() # Representations - if(SKLEARN_FOUND AND MATPLOTLIB_FOUND) + if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) add_gudhi_py_test(test_representations) endif() diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 8ebd7888..43c914f3 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -41,15 +41,7 @@ def test_multiple(): assert d1 == pytest.approx(d2) assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) d1 = pairwise_persistence_diagram_distances(l1, l2, metric="wasserstein", order=2, internal_p=2) - mode = "" - try: - import ot - mode = "pot" - except ImportError: - print("POT is not available, try with hera") - mode = "hera" - - d2 = WassersteinDistance(order=2, internal_p=2, mode=mode, n_jobs=4).fit(l2).transform(l1) + d2 = WassersteinDistance(order=2, internal_p=2, n_jobs=4).fit(l2).transform(l1) print(d1.shape, d2.shape) assert d1 == pytest.approx(d2, rel=0.02) -- cgit v1.2.3 From fda0084941ece5d41a258d19ca4eb0b3d87384a4 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 9 Dec 2020 09:41:13 +0100 Subject: Fix #388 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 1 - src/python/CMakeLists.txt | 1 + src/python/gudhi/simplex_tree.pxd | 2 ++ src/python/gudhi/simplex_tree.pyx | 3 +++ src/python/include/Simplex_tree_interface.h | 10 +++++++++- src/python/test/test_simplex_tree.py | 14 +++++++++----- 6 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src/python/test') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index e2684aa4..e1566877 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -58,7 +58,6 @@ endif(WITH_GUDHI_USE_TBB) set(CGAL_WITH_EIGEN3_VERSION 0.0.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) - add_definitions(-DGUDHI_USE_EIGEN3) include( ${EIGEN3_USE_FILE} ) set(CGAL_WITH_EIGEN3_VERSION ${CGAL_VERSION}) endif (EIGEN3_FOUND) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 2d5f793a..45c89609 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -133,6 +133,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") # No problem, even if no CGAL found set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_EIGEN3', ") endif (EIGEN3_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 3c4cbed3..283830ff 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -74,6 +74,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + + + cdef int _GUDHI_USE_EIGEN3 cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 7d6ab89a..eb44c0fc 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -17,6 +17,9 @@ __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" +# For unitary tests purpose +__GUDHI_USE_EIGEN3 = _GUDHI_USE_EIGEN3 + # SimplexTree python interface cdef class SimplexTree: """The simplex tree is an efficient and flexible data structure for diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 2bd704b4..50592e25 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -27,6 +27,12 @@ namespace Gudhi { +#ifdef GUDHI_USE_EIGEN3 +const int _GUDHI_USE_EIGEN3 = 1; +#else +const int _GUDHI_USE_EIGEN3 = 0; +#endif + template class Simplex_tree_interface : public Simplex_tree { public: @@ -191,7 +197,9 @@ class Simplex_tree_interface : public Simplex_tree { } return collapsed_stree_ptr; #else - return this; + // If no Eigen3, return a copy, as it will be deleted in pyx + Simplex_tree_interface* collapsed_stree_ptr = new Simplex_tree_interface(*this); + return collapsed_stree_ptr; #endif } diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 3b23fa0b..15b472ee 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -8,7 +8,7 @@ - YYYY/MM Author: Description of the modification """ -from gudhi import SimplexTree +from gudhi import SimplexTree, simplex_tree import pytest __author__ = "Vincent Rouvreau" @@ -353,11 +353,15 @@ def test_collapse_edges(): assert st.num_simplices() == 10 + # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning st.collapse_edges() - assert st.num_simplices() == 9 - assert st.find([1, 3]) == False - for simplex in st.get_skeleton(0): - assert simplex[1] == 1. + if simplex_tree.__GUDHI_USE_EIGEN3: + assert st.num_simplices() == 9 + assert st.find([1, 3]) == False + for simplex in st.get_skeleton(0): + assert simplex[1] == 1. + else: + assert st.num_simplices() == 10 def test_reset_filtration(): st = SimplexTree() -- cgit v1.2.3 From 957da77f9484972ce34d0415502887f92080878e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Dec 2020 09:38:12 +0100 Subject: code review: GUDHI_USE_EIGEN3 generated by CMake in __init__.py as suggested and roll back the other solution --- src/python/CMakeLists.txt | 2 ++ src/python/gudhi/__init__.py.in | 4 ++++ src/python/gudhi/simplex_tree.pxd | 2 -- src/python/gudhi/simplex_tree.pyx | 3 --- src/python/include/Simplex_tree_interface.h | 6 ------ src/python/test/test_simplex_tree.py | 4 ++-- 6 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/python/test') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 45c89609..5a245aac 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -129,11 +129,13 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") endif() + set(GUDHI_USE_EIGEN3 "False") if (EIGEN3_FOUND) add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") # No problem, even if no CGAL found set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_EIGEN3', ") + set(GUDHI_USE_EIGEN3 "True") endif (EIGEN3_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") diff --git a/src/python/gudhi/__init__.py.in b/src/python/gudhi/__init__.py.in index 79e12fbc..3043201a 100644 --- a/src/python/gudhi/__init__.py.in +++ b/src/python/gudhi/__init__.py.in @@ -23,6 +23,10 @@ __all__ = [@GUDHI_PYTHON_MODULES@ @GUDHI_PYTHON_MODULES_EXTRA@] __available_modules = '' __missing_modules = '' +# For unitary tests purpose +# could use "if 'collapse_edges' in gudhi.__all__" when collapse edges will have a python module +__GUDHI_USE_EIGEN3 = @GUDHI_USE_EIGEN3@ + # Try to import * from gudhi.__module_name for default modules. # Extra modules require an explicit import by the user (mostly because of # unusual dependencies, but also to avoid cluttering namespace gudhi and diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 283830ff..3c4cbed3 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -74,8 +74,6 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + - - cdef int _GUDHI_USE_EIGEN3 cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index eb44c0fc..7d6ab89a 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -17,9 +17,6 @@ __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" -# For unitary tests purpose -__GUDHI_USE_EIGEN3 = _GUDHI_USE_EIGEN3 - # SimplexTree python interface cdef class SimplexTree: """The simplex tree is an efficient and flexible data structure for diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 50592e25..82444609 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -27,12 +27,6 @@ namespace Gudhi { -#ifdef GUDHI_USE_EIGEN3 -const int _GUDHI_USE_EIGEN3 = 1; -#else -const int _GUDHI_USE_EIGEN3 = 0; -#endif - template class Simplex_tree_interface : public Simplex_tree { public: diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 15b472ee..0c072baa 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -8,7 +8,7 @@ - YYYY/MM Author: Description of the modification """ -from gudhi import SimplexTree, simplex_tree +from gudhi import SimplexTree, __GUDHI_USE_EIGEN3 import pytest __author__ = "Vincent Rouvreau" @@ -355,7 +355,7 @@ def test_collapse_edges(): # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning st.collapse_edges() - if simplex_tree.__GUDHI_USE_EIGEN3: + if __GUDHI_USE_EIGEN3: assert st.num_simplices() == 9 assert st.find([1, 3]) == False for simplex in st.get_skeleton(0): -- cgit v1.2.3 From 40e0976e8dae27f0e30f3c9df1fd7de1a7343948 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Dec 2020 10:31:09 +0100 Subject: code review: throw an eception if collapse_edges when no Eigen3 --- src/python/gudhi/simplex_tree.pxd | 2 +- src/python/gudhi/simplex_tree.pyx | 4 ++-- src/python/include/Simplex_tree_interface.h | 4 +--- src/python/test/test_simplex_tree.py | 7 ++++--- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src/python/test') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 3c4cbed3..000323af 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -63,7 +63,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool make_filtration_non_decreasing() nogil void compute_extended_filtration() nogil vector[vector[pair[int, pair[double, double]]]] compute_extended_persistence_subdiagrams(vector[pair[int, pair[double, double]]] dgm, double min_persistence) nogil - Simplex_tree_interface_full_featured* collapse_edges(int nb_collapse_iteration) nogil + Simplex_tree_interface_full_featured* collapse_edges(int nb_collapse_iteration) nogil except + void reset_filtration(double filtration, int dimension) nogil # Iterators over Simplex tree pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) nogil diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 7d6ab89a..665d41e6 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -628,8 +628,8 @@ cdef class SimplexTree: :param nb_iterations: The number of edge collapse iterations to perform. Default is 1. :type nb_iterations: int - :note: collapse_edges function requires `Eigen `_ >= 3.1.0, otherwise no action is - performed. + :note: collapse_edges method requires `Eigen `_ >= 3.1.0 and an exception is thrown + if this method is not available. """ # Backup old pointer cdef Simplex_tree_interface_full_featured* ptr = self.get_ptr() diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 82444609..629f6083 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -191,9 +191,7 @@ class Simplex_tree_interface : public Simplex_tree { } return collapsed_stree_ptr; #else - // If no Eigen3, return a copy, as it will be deleted in pyx - Simplex_tree_interface* collapsed_stree_ptr = new Simplex_tree_interface(*this); - return collapsed_stree_ptr; + throw std::runtime_error("Unable to collapse edges as it requires Eigen3 >= 3.1.0."); #endif } diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 0c072baa..a3eacaa9 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -353,15 +353,16 @@ def test_collapse_edges(): assert st.num_simplices() == 10 - # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning - st.collapse_edges() if __GUDHI_USE_EIGEN3: + st.collapse_edges() assert st.num_simplices() == 9 assert st.find([1, 3]) == False for simplex in st.get_skeleton(0): assert simplex[1] == 1. else: - assert st.num_simplices() == 10 + # If no Eigen3, collapse_edges throws an exception + with pytest.raises(RuntimeError): + st.collapse_edges() def test_reset_filtration(): st = SimplexTree() -- cgit v1.2.3 From 0afc650917ddf9fc4cf95fd86e0b6408f64a465d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 11 Jan 2021 11:29:20 +0100 Subject: Remove sphinx doc test for atol as points order can be inverted and add it in a UT but sorted --- src/python/gudhi/representations/vector_methods.py | 14 +++++++------- src/python/test/test_representations.py | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'src/python/test') diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index cdcb1fde..d4449e7d 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -606,16 +606,16 @@ class Atol(BaseEstimator, TransformerMixin): >>> c = np.array([[3, 2, -1], [1, 2, -1]]) >>> atol_vectoriser = Atol(quantiser=KMeans(n_clusters=2, random_state=202006)) >>> atol_vectoriser.fit(X=[a, b, c]).centers - array([[ 2. , 0.66666667, 3.33333333], - [ 2.6 , 2.8 , -0.4 ]]) + >>> # array([[ 2. , 0.66666667, 3.33333333], + >>> # [ 2.6 , 2.8 , -0.4 ]]) >>> atol_vectoriser(a) - array([1.18168665, 0.42375966]) + >>> # array([1.18168665, 0.42375966]) >>> atol_vectoriser(c) - array([0.02062512, 1.25157463]) + >>> # array([0.02062512, 1.25157463]) >>> atol_vectoriser.transform(X=[a, b, c]) - array([[1.18168665, 0.42375966], - [0.29861028, 1.06330156], - [0.02062512, 1.25157463]]) + >>> # array([[1.18168665, 0.42375966], + >>> # [0.29861028, 1.06330156], + >>> # [0.02062512, 1.25157463]]) """ def __init__(self, quantiser, weighting_method="cloud", contrast="gaussian"): """ diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 43c914f3..1c8f8cdb 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -46,6 +46,24 @@ def test_multiple(): assert d1 == pytest.approx(d2, rel=0.02) +# Test sorted values as points order can be inverted, and sorted test is not documentation-friendly +def test_atol_doc(): + a = np.array([[1, 2, 4], [1, 4, 0], [1, 0, 4]]) + b = np.array([[4, 2, 0], [4, 4, 0], [4, 0, 2]]) + c = np.array([[3, 2, -1], [1, 2, -1]]) + + atol_vectoriser = Atol(quantiser=KMeans(n_clusters=2, random_state=202006)) + assert np.sort(atol_vectoriser.fit(X=[a, b, c]).centers, axis=0) == \ + pytest.approx(np.array([[2. , 0.66666667, -0.4], \ + [2.6, 2.8 , 3.33333333]])) + assert np.sort(atol_vectoriser(a)) == pytest.approx(np.array([0.42375966, 1.18168665])) + assert np.sort(atol_vectoriser(c)) == pytest.approx(np.array([0.02062512, 1.25157463])) + assert np.sort(atol_vectoriser.transform(X=[a, b, c]), axis=0) == \ + pytest.approx(np.array([[0.02062512, 0.42375966], \ + [0.29861028, 1.06330156], \ + [1.18168665, 1.25157463]])) + + def test_dummy_atol(): a = np.array([[1, 2, 4], [1, 4, 0], [1, 0, 4]]) b = np.array([[4, 2, 0], [4, 4, 0], [4, 0, 2]]) -- cgit v1.2.3 From 60907b0104a2807667f175d9a8a328fd3f7f4ec8 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 11 Jan 2021 16:25:18 +0100 Subject: Ignore doctest for atol doc. Rewrite unitary test for atol doc. To be synchronized --- src/python/gudhi/representations/vector_methods.py | 9 ++++---- src/python/test/test_representations.py | 26 ++++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src/python/test') diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 5ec2abd0..84bc99a2 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -605,18 +605,19 @@ class Atol(BaseEstimator, TransformerMixin): >>> b = np.array([[4, 2, 0], [4, 4, 0], [4, 0, 2]]) >>> c = np.array([[3, 2, -1], [1, 2, -1]]) >>> atol_vectoriser = Atol(quantiser=KMeans(n_clusters=2, random_state=202006)) - >>> atol_vectoriser.fit(X=[a, b, c]).centers #doctest: +SKIP + >>> atol_vectoriser.fit(X=[a, b, c]).centers # doctest: +SKIP >>> # array([[ 2. , 0.66666667, 3.33333333], >>> # [ 2.6 , 2.8 , -0.4 ]]) >>> atol_vectoriser(a) - >>> # array([1.18168665, 0.42375966]) #doctest: +SKIP + >>> # array([1.18168665, 0.42375966]) # doctest: +SKIP >>> atol_vectoriser(c) - >>> # array([0.02062512, 1.25157463]) #doctest: +SKIP - >>> atol_vectoriser.transform(X=[a, b, c]) #doctest: +SKIP + >>> # array([0.02062512, 1.25157463]) # doctest: +SKIP + >>> atol_vectoriser.transform(X=[a, b, c]) # doctest: +SKIP >>> # array([[1.18168665, 0.42375966], >>> # [0.29861028, 1.06330156], >>> # [0.02062512, 1.25157463]]) """ + # Note the example above must be up to date with the one in tests called test_atol_doc def __init__(self, quantiser, weighting_method="cloud", contrast="gaussian"): """ Constructor for the Atol measure vectorisation class. diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 1c8f8cdb..cda1a15b 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -47,21 +47,29 @@ def test_multiple(): # Test sorted values as points order can be inverted, and sorted test is not documentation-friendly +# Note the test below must be up to date with the Atol class documentation def test_atol_doc(): a = np.array([[1, 2, 4], [1, 4, 0], [1, 0, 4]]) b = np.array([[4, 2, 0], [4, 4, 0], [4, 0, 2]]) c = np.array([[3, 2, -1], [1, 2, -1]]) atol_vectoriser = Atol(quantiser=KMeans(n_clusters=2, random_state=202006)) - assert np.sort(atol_vectoriser.fit(X=[a, b, c]).centers, axis=0) == \ - pytest.approx(np.array([[2. , 0.66666667, -0.4], \ - [2.6, 2.8 , 3.33333333]])) - assert np.sort(atol_vectoriser(a)) == pytest.approx(np.array([0.42375966, 1.18168665])) - assert np.sort(atol_vectoriser(c)) == pytest.approx(np.array([0.02062512, 1.25157463])) - assert np.sort(atol_vectoriser.transform(X=[a, b, c]), axis=0) == \ - pytest.approx(np.array([[0.02062512, 0.42375966], \ - [0.29861028, 1.06330156], \ - [1.18168665, 1.25157463]])) + # Atol will do + # X = np.concatenate([a,b,c]) + # kmeans = KMeans(n_clusters=2, random_state=202006).fit(X) + # kmeans.labels_ will be : array([1, 0, 1, 0, 0, 1, 0, 0]) + first_cluster = np.asarray([a[0], a[2], b[2]]) + second_cluster = np.asarray([a[1], b[0], b[2], c[0], c[1]]) + + # Check the center of the first_cluster and second_cluster are in Atol centers + centers = atol_vectoriser.fit(X=[a, b, c]).centers + np.isclose(centers, first_cluster.mean(axis=0)).all(1).any() + np.isclose(centers, second_cluster.mean(axis=0)).all(1).any() + + vectorization = atol_vectoriser.transform(X=[a, b, c]) + assert np.allclose(vectorization[0], atol_vectoriser(a)) + assert np.allclose(vectorization[1], atol_vectoriser(b)) + assert np.allclose(vectorization[2], atol_vectoriser(c)) def test_dummy_atol(): -- cgit v1.2.3