diff options
author | Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> | 2022-11-14 10:52:55 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-14 10:52:55 +0100 |
commit | 3e30893ee41aba1311f6338eda2060cae2b9507d (patch) | |
tree | 624ca76aa9dbfa6a8b9ad174f007e5ee25432475 | |
parent | 79d858ec3f71f5f6311d8671a2088078e3272204 (diff) | |
parent | f4f930169fbf2db2707d69b334cfe5b941c64350 (diff) |
Merge pull request #727 from mglisse/writeoff
New write_points_to_off_file
-rw-r--r-- | src/python/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/python/doc/installation.rst | 4 | ||||
-rw-r--r-- | src/python/doc/point_cloud.rst | 5 | ||||
-rw-r--r-- | src/python/gudhi/off_utils.pyx (renamed from src/python/gudhi/off_reader.pyx) | 23 | ||||
-rw-r--r-- | src/python/test/test_off.py | 21 | ||||
-rwxr-xr-x | src/python/test/test_subsampling.py | 103 |
6 files changed, 75 insertions, 86 deletions
diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 8f8df138..32ec13bd 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -53,7 +53,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets', ") # Cython modules - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ") + set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_utils', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'simplex_tree', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'rips_complex', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'cubical_complex', ") @@ -152,7 +152,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") endif (EIGEN3_FOUND) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_utils', ") 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', ") @@ -546,6 +546,7 @@ if(PYTHONINTERP_FOUND) # Reader utils add_gudhi_py_test(test_reader_utils) + add_gudhi_py_test(test_off) # Wasserstein if(OT_FOUND) diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 276ac4e2..5491542f 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -150,7 +150,7 @@ You shall have something like: Cython version 0.29.25 Numpy version 1.21.4 Boost version 1.77.0 - + Installed modules are: off_reader;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; + + Installed modules are: off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex; + Missing modules are: bottleneck;nerve_gic;subsampling;tangential_complex;alpha_complex;euclidean_witness_complex; euclidean_strong_witness_complex; @@ -188,7 +188,7 @@ A complete configuration would be : GMPXX_LIBRARIES = /usr/lib/x86_64-linux-gnu/libgmpxx.so MPFR_LIBRARIES = /usr/lib/x86_64-linux-gnu/libmpfr.so TBB version 9107 found and used - + Installed modules are: bottleneck;off_reader;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; + + Installed modules are: bottleneck;off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex;nerve_gic;subsampling; tangential_complex;alpha_complex;euclidean_witness_complex;euclidean_strong_witness_complex; + Missing modules are: diff --git a/src/python/doc/point_cloud.rst b/src/python/doc/point_cloud.rst index ffd8f85b..473b303f 100644 --- a/src/python/doc/point_cloud.rst +++ b/src/python/doc/point_cloud.rst @@ -13,6 +13,11 @@ File Readers .. autofunction:: gudhi.read_lower_triangular_matrix_from_csv_file +File Writers +------------ + +.. autofunction:: gudhi.write_points_to_off_file + Subsampling ----------- diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_utils.pyx index a3200704..9276c7b0 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_utils.pyx @@ -13,8 +13,10 @@ from __future__ import print_function from cython cimport numeric from libcpp.vector cimport vector from libcpp.string cimport string +cimport cython import errno import os +import numpy as np __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -24,7 +26,7 @@ cdef extern from "Off_reader_interface.h" namespace "Gudhi": vector[vector[double]] read_points_from_OFF_file(string off_file) def read_points_from_off_file(off_file=''): - """Read points from OFF file. + """Read points from an `OFF file <fileformats.html#off-file-format>`_. :param off_file: An OFF file style name. :type off_file: string @@ -39,3 +41,22 @@ def read_points_from_off_file(off_file=''): raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), off_file) +@cython.embedsignature(True) +def write_points_to_off_file(fname, points): + """Write points to an `OFF file <fileformats.html#off-file-format>`_. + + A simple wrapper for `numpy.savetxt`. + + :param fname: Name of the OFF file. + :type fname: str or file handle + :param points: Point coordinates. + :type points: numpy array of shape (n, dim) + """ + points = np.array(points, copy=False) + assert len(points.shape) == 2 + dim = points.shape[1] + if dim == 3: + head = 'OFF\n{} 0 0'.format(points.shape[0]) + else: + head = 'nOFF\n{} {} 0 0'.format(dim, points.shape[0]) + np.savetxt(fname, points, header=head, comments='') diff --git a/src/python/test/test_off.py b/src/python/test/test_off.py new file mode 100644 index 00000000..aea1941b --- /dev/null +++ b/src/python/test/test_off.py @@ -0,0 +1,21 @@ +""" This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + Author(s): Marc Glisse + + Copyright (C) 2022 Inria + + Modification(s): + - YYYY/MM Author: Description of the modification +""" + +import gudhi as gd +import numpy as np +import pytest + + +def test_off_rw(): + for dim in range(2, 6): + X = np.random.rand(123, dim) + gd.write_points_to_off_file("rand.off", X) + Y = gd.read_points_from_off_file("rand.off") + assert Y == pytest.approx(X) diff --git a/src/python/test/test_subsampling.py b/src/python/test/test_subsampling.py index 3431f372..c1cb4e3f 100755 --- a/src/python/test/test_subsampling.py +++ b/src/python/test/test_subsampling.py @@ -16,17 +16,9 @@ __license__ = "MIT" def test_write_off_file_for_tests(): - file = open("subsample.off", "w") - file.write("nOFF\n") - file.write("2 7 0 0\n") - file.write("1.0 1.0\n") - file.write("7.0 0.0\n") - file.write("4.0 6.0\n") - file.write("9.0 6.0\n") - file.write("0.0 14.0\n") - file.write("2.0 19.0\n") - file.write("9.0 17.0\n") - file.close() + gudhi.write_points_to_off_file( + "subsample.off", [[1.0, 1.0], [7.0, 0.0], [4.0, 6.0], [9.0, 6.0], [0.0, 14.0], [2.0, 19.0], [9.0, 17.0]] + ) def test_simple_choose_n_farthest_points_with_a_starting_point(): @@ -34,54 +26,29 @@ def test_simple_choose_n_farthest_points_with_a_starting_point(): i = 0 for point in point_set: # The iteration starts with the given starting point - sub_set = gudhi.choose_n_farthest_points( - points=point_set, nb_points=1, starting_point=i - ) + sub_set = gudhi.choose_n_farthest_points(points=point_set, nb_points=1, starting_point=i) assert sub_set[0] == point_set[i] i = i + 1 # The iteration finds then the farthest - sub_set = gudhi.choose_n_farthest_points( - points=point_set, nb_points=2, starting_point=1 - ) + sub_set = gudhi.choose_n_farthest_points(points=point_set, nb_points=2, starting_point=1) assert sub_set[1] == point_set[3] - sub_set = gudhi.choose_n_farthest_points( - points=point_set, nb_points=2, starting_point=3 - ) + sub_set = gudhi.choose_n_farthest_points(points=point_set, nb_points=2, starting_point=3) assert sub_set[1] == point_set[1] - sub_set = gudhi.choose_n_farthest_points( - points=point_set, nb_points=2, starting_point=0 - ) + sub_set = gudhi.choose_n_farthest_points(points=point_set, nb_points=2, starting_point=0) assert sub_set[1] == point_set[2] - sub_set = gudhi.choose_n_farthest_points( - points=point_set, nb_points=2, starting_point=2 - ) + sub_set = gudhi.choose_n_farthest_points(points=point_set, nb_points=2, starting_point=2) assert sub_set[1] == point_set[0] # Test the limits - assert ( - gudhi.choose_n_farthest_points(points=[], nb_points=0, starting_point=0) == [] - ) - assert ( - gudhi.choose_n_farthest_points(points=[], nb_points=1, starting_point=0) == [] - ) - assert ( - gudhi.choose_n_farthest_points(points=[], nb_points=0, starting_point=1) == [] - ) - assert ( - gudhi.choose_n_farthest_points(points=[], nb_points=1, starting_point=1) == [] - ) + assert gudhi.choose_n_farthest_points(points=[], nb_points=0, starting_point=0) == [] + assert gudhi.choose_n_farthest_points(points=[], nb_points=1, starting_point=0) == [] + assert gudhi.choose_n_farthest_points(points=[], nb_points=0, starting_point=1) == [] + assert gudhi.choose_n_farthest_points(points=[], nb_points=1, starting_point=1) == [] # From off file test for i in range(0, 7): - assert ( - len( - gudhi.choose_n_farthest_points( - off_file="subsample.off", nb_points=i, starting_point=i - ) - ) - == i - ) + assert len(gudhi.choose_n_farthest_points(off_file="subsample.off", nb_points=i, starting_point=i)) == i def test_simple_choose_n_farthest_points_randomed(): @@ -104,10 +71,7 @@ def test_simple_choose_n_farthest_points_randomed(): # From off file test for i in range(0, 7): - assert ( - len(gudhi.choose_n_farthest_points(off_file="subsample.off", nb_points=i)) - == i - ) + assert len(gudhi.choose_n_farthest_points(off_file="subsample.off", nb_points=i)) == i def test_simple_pick_n_random_points(): @@ -130,9 +94,7 @@ def test_simple_pick_n_random_points(): # From off file test for i in range(0, 7): - assert ( - len(gudhi.pick_n_random_points(off_file="subsample.off", nb_points=i)) == i - ) + assert len(gudhi.pick_n_random_points(off_file="subsample.off", nb_points=i)) == i def test_simple_sparsify_points(): @@ -152,31 +114,10 @@ def test_simple_sparsify_points(): ] 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)) - == 7 - ) - assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=30.0)) - == 5 - ) - assert ( - 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=89.9)) - == 3 - ) - assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=100.0)) - == 2 - ) - assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=324.9)) - == 2 - ) - assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=325.01)) - == 1 - ) + assert len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=0.0)) == 7 + assert len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=30.0)) == 5 + assert 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=89.9)) == 3 + assert len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=100.0)) == 2 + assert len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=324.9)) == 2 + assert len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=325.01)) == 1 |