diff options
author | ROUVREAU Vincent <vincent.rouvreau@inria.fr> | 2021-03-15 19:19:58 +0100 |
---|---|---|
committer | ROUVREAU Vincent <vincent.rouvreau@inria.fr> | 2021-03-15 19:19:58 +0100 |
commit | d2ae3d4e9f17649813f64bbc3b00d540b23f21dd (patch) | |
tree | f336fe75a32d469e50a6a52304a9616680cef498 | |
parent | a1674773ce5ed9060e5ecf173e5b75cd22f85b1a (diff) |
Add read_weights in reader_utils. Add exceptions for file not found and inconsistency in alpha ctor. Add UT accordingly
-rw-r--r-- | src/python/gudhi/alpha_complex.pyx | 41 | ||||
-rw-r--r-- | src/python/gudhi/reader_utils.pyx | 16 | ||||
-rwxr-xr-x | src/python/test/test_alpha_complex.py | 55 | ||||
-rwxr-xr-x | src/python/test/test_reader_utils.py | 49 |
4 files changed, 139 insertions, 22 deletions
diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index 0fea3f37..b7c20f74 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -16,11 +16,12 @@ from libcpp.utility cimport pair from libcpp.string cimport string from libcpp cimport bool from libc.stdint cimport intptr_t +import errno import os from gudhi.simplex_tree cimport * from gudhi.simplex_tree import SimplexTree -from gudhi import read_points_from_off_file +from gudhi import read_points_from_off_file, read_weights __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -55,7 +56,7 @@ cdef class AlphaComplex: cdef Alpha_complex_interface * this_ptr # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=None, off_file='', precision='safe'): + def __init__(self, points=[], off_file='', weights=[], weight_file='', precision='safe'): """AlphaComplex constructor. :param points: A list of points in d-Dimension. @@ -65,12 +66,24 @@ cdef class AlphaComplex: read and overwritten by the points in the `off_file`. :type off_file: string + :param weights: A list of weights. If set, the number of weights must correspond to the + number of points. + :type weights: list of double + + :param weight_file: A file containing a list of weights (one per line). + `weights` are read and overwritten by the weights in the `weight_file`. + If set, the number of weights must correspond to the number of points. + :type weight_file: string + :param precision: Alpha complex precision can be 'fast', 'safe' or 'exact'. Default is 'safe'. :type precision: string + + :raises FileNotFoundError: If `off_file` and/or `weight_file` is set but not found. + :raises ValueError: In case of inconsistency between the number of points and weights. """ # The real cython constructor - def __cinit__(self, points = [], off_file = '', precision = 'safe'): + def __cinit__(self, points = [], off_file = '', weights=[], weight_file='', precision = 'safe'): assert precision in ['fast', 'safe', 'exact'], "Alpha complex precision can only be 'fast', 'safe' or 'exact'" cdef bool fast = precision == 'fast' cdef bool exact = precision == 'exact' @@ -79,12 +92,28 @@ cdef class AlphaComplex: if os.path.isfile(off_file): points = read_points_from_off_file(off_file = off_file) else: - print("file " + off_file + " not found.") + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), off_file) + + if weight_file: + if os.path.isfile(weight_file): + weights = read_weights(weight_file = weight_file) + else: + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), weight_file) + # need to copy the points to use them without the gil cdef vector[vector[double]] pts + cdef vector[double] wgts pts = points - with nogil: - self.this_ptr = new Alpha_complex_interface(pts, fast, exact) + if len(weights) == 0: + with nogil: + self.this_ptr = new Alpha_complex_interface(pts, fast, exact) + else: + if len(weights) == len(points): + wgts = weights + with nogil: + self.this_ptr = new Alpha_complex_interface(pts, fast, exact) + else: + raise ValueError("Inconsistency between the number of points and weights") def __dealloc__(self): if self.this_ptr != NULL: diff --git a/src/python/gudhi/reader_utils.pyx b/src/python/gudhi/reader_utils.pyx index fe1c3a2e..f997ad3e 100644 --- a/src/python/gudhi/reader_utils.pyx +++ b/src/python/gudhi/reader_utils.pyx @@ -84,3 +84,19 @@ def read_persistence_intervals_in_dimension(persistence_file='', only_this_dim=- 'utf-8'), only_this_dim)) print("file " + persistence_file + " not set or not found.") return [] + +def read_weights(weight_file=''): + """Reads a file containing weights. Only one float value per line is read and stored. + The return value is a `list(weight)`. + + :param weight_file: A weight file style name (one weight per line). + :type weight_file: string + + :returns: A list of weights. + :rtype: List[float] + """ + weights=[] + with open(weight_file, 'r') as wfile: + weights = [float(wline) for wline in wfile if wline.strip()] + return weights + diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 8f1424ec..35059339 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -261,3 +261,58 @@ def _3d_tetrahedrons(precision): def test_3d_tetrahedrons(): for precision in ['fast', 'safe', 'exact']: _3d_tetrahedrons(precision) + +def test_non_existing_off_file(): + with pytest.raises(FileNotFoundError): + alpha = gd.AlphaComplex(off_file="pouetpouettralala.toubiloubabdou") + +def test_non_existing_weight_file(): + off_file = open("alphacomplexdoc.off", "w") + off_file.write("OFF \n" \ + "7 0 0 \n" \ + "1.0 1.0 0.0\n" \ + "7.0 0.0 0.0\n" \ + "4.0 6.0 0.0\n" \ + "9.0 6.0 0.0\n" \ + "0.0 14.0 0.0\n" \ + "2.0 19.0 0.0\n" \ + "9.0 17.0 0.0\n" ) + off_file.close() + + with pytest.raises(FileNotFoundError): + alpha = gd.AlphaComplex(off_file="alphacomplexdoc.off", + weight_file="pouetpouettralala.toubiloubabdou") + + +def test_inconsistency_off_weight_file(): + off_file = open("alphacomplexdoc.off", "w") + off_file.write("OFF \n" \ + "7 0 0 \n" \ + "1.0 1.0 0.0\n" \ + "7.0 0.0 0.0\n" \ + "4.0 6.0 0.0\n" \ + "9.0 6.0 0.0\n" \ + "0.0 14.0 0.0\n" \ + "2.0 19.0 0.0\n" \ + "9.0 17.0 0.0\n" ) + off_file.close() + # 7 points, 8 weights, on purpose + weight_file = open("alphacomplexdoc.wgt", "w") + weight_file.write("5.0\n" \ + "2.0\n" \ + "7.0\n" \ + "4.0\n" \ + "9.0\n" \ + "0.0\n" \ + "2.0\n" \ + "9.0\n" ) + weight_file.close() + + with pytest.raises(ValueError): + alpha = gd.AlphaComplex(off_file="alphacomplexdoc.off", + weight_file="alphacomplexdoc.wgt") + + # 7 points, 6 weights, on purpose + with pytest.raises(ValueError): + alpha = gd.AlphaComplex(off_file="alphacomplexdoc.off", + weights=[1., 2., 3., 4., 5., 6.]) diff --git a/src/python/test/test_reader_utils.py b/src/python/test/test_reader_utils.py index 90da6651..91de9ba0 100755 --- a/src/python/test/test_reader_utils.py +++ b/src/python/test/test_reader_utils.py @@ -8,8 +8,9 @@ - YYYY/MM Author: Description of the modification """ -import gudhi +import gudhi as gd import numpy as np +from pytest import raises __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2017 Inria" @@ -18,7 +19,7 @@ __license__ = "MIT" def test_non_existing_csv_file(): # Try to open a non existing file - matrix = gudhi.read_lower_triangular_matrix_from_csv_file( + matrix = gd.read_lower_triangular_matrix_from_csv_file( csv_file="pouetpouettralala.toubiloubabdou" ) assert matrix == [] @@ -29,7 +30,7 @@ def test_full_square_distance_matrix_csv_file(): test_file = open("full_square_distance_matrix.csv", "w") test_file.write("0;1;2;3;\n1;0;4;5;\n2;4;0;6;\n3;5;6;0;") test_file.close() - matrix = gudhi.read_lower_triangular_matrix_from_csv_file( + matrix = gd.read_lower_triangular_matrix_from_csv_file( csv_file="full_square_distance_matrix.csv" ) assert matrix == [[], [1.0], [2.0, 4.0], [3.0, 5.0, 6.0]] @@ -40,7 +41,7 @@ def test_lower_triangular_distance_matrix_csv_file(): test_file = open("lower_triangular_distance_matrix.csv", "w") test_file.write("\n1,\n2,3,\n4,5,6,\n7,8,9,10,") test_file.close() - matrix = gudhi.read_lower_triangular_matrix_from_csv_file( + matrix = gd.read_lower_triangular_matrix_from_csv_file( csv_file="lower_triangular_distance_matrix.csv", separator="," ) assert matrix == [[], [1.0], [2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0, 10.0]] @@ -48,11 +49,11 @@ def test_lower_triangular_distance_matrix_csv_file(): def test_non_existing_persistence_file(): # Try to open a non existing file - persistence = gudhi.read_persistence_intervals_grouped_by_dimension( + persistence = gd.read_persistence_intervals_grouped_by_dimension( persistence_file="pouetpouettralala.toubiloubabdou" ) assert persistence == [] - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="pouetpouettralala.toubiloubabdou", only_this_dim=1 ) np.testing.assert_array_equal(persistence, []) @@ -65,21 +66,21 @@ def test_read_persistence_intervals_without_dimension(): "# Simple persistence diagram without dimension\n2.7 3.7\n9.6 14.\n34.2 34.974\n3. inf" ) test_file.close() - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_without_dimension.pers" ) np.testing.assert_array_equal( persistence, [(2.7, 3.7), (9.6, 14.0), (34.2, 34.974), (3.0, float("Inf"))] ) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_without_dimension.pers", only_this_dim=0 ) np.testing.assert_array_equal(persistence, []) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_without_dimension.pers", only_this_dim=1 ) np.testing.assert_array_equal(persistence, []) - persistence = gudhi.read_persistence_intervals_grouped_by_dimension( + persistence = gd.read_persistence_intervals_grouped_by_dimension( persistence_file="persistence_intervals_without_dimension.pers" ) assert persistence == { @@ -94,29 +95,29 @@ def test_read_persistence_intervals_with_dimension(): "# Simple persistence diagram with dimension\n0 2.7 3.7\n1 9.6 14.\n3 34.2 34.974\n1 3. inf" ) test_file.close() - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_with_dimension.pers" ) np.testing.assert_array_equal( persistence, [(2.7, 3.7), (9.6, 14.0), (34.2, 34.974), (3.0, float("Inf"))] ) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_with_dimension.pers", only_this_dim=0 ) np.testing.assert_array_equal(persistence, [(2.7, 3.7)]) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_with_dimension.pers", only_this_dim=1 ) np.testing.assert_array_equal(persistence, [(9.6, 14.0), (3.0, float("Inf"))]) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_with_dimension.pers", only_this_dim=2 ) np.testing.assert_array_equal(persistence, []) - persistence = gudhi.read_persistence_intervals_in_dimension( + persistence = gd.read_persistence_intervals_in_dimension( persistence_file="persistence_intervals_with_dimension.pers", only_this_dim=3 ) np.testing.assert_array_equal(persistence, [(34.2, 34.974)]) - persistence = gudhi.read_persistence_intervals_grouped_by_dimension( + persistence = gd.read_persistence_intervals_grouped_by_dimension( persistence_file="persistence_intervals_with_dimension.pers" ) assert persistence == { @@ -124,3 +125,19 @@ def test_read_persistence_intervals_with_dimension(): 1: [(9.6, 14.0), (3.0, float("Inf"))], 3: [(34.2, 34.974)], } + + +def test_non_existing_weights_file(): + with raises(FileNotFoundError): + # Try to open a non existing file + persistence = gd.read_weights(weight_file="pouetpouettralala.toubiloubabdou") + +def test_read_weights(): + # Create test file + test_file = open("test_read_weights.wgt", "w") + test_file.write( + "2.7\n 9.6 \n\t34.2\n3.\t\n\n" + ) + test_file.close() + weights = gd.read_weights(weight_file = "test_read_weights.wgt") + assert weights == [2.7, 9.6, 34.2, 3.] |