From 1ef113ff6f5db7288e4dc4c18c053b18d90dbf1a Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Fri, 30 Apr 2021 11:17:35 +0200 Subject: First version of points generation on torus --- src/python/CMakeLists.txt | 4 ++ .../gudhi/datasets/generators/points/__init__.py | 0 .../gudhi/datasets/generators/points/_torus.cc | 70 ++++++++++++++++++++++ .../gudhi/datasets/generators/points/torus.py | 52 ++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/python/gudhi/datasets/generators/points/__init__.py create mode 100644 src/python/gudhi/datasets/generators/points/_torus.cc create mode 100644 src/python/gudhi/datasets/generators/points/torus.py (limited to 'src') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index a1440cbc..1b9db2b5 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -46,6 +46,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'clustering', ") + set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets/generators/points', ") endif() if(CYTHON_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ") @@ -151,6 +152,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/wasserstein', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/bottleneck', ") if (NOT CGAL_VERSION VERSION_LESS 4.11.0) + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/points/_torus', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'bottleneck', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") endif () @@ -262,6 +264,8 @@ if(PYTHONINTERP_FOUND) file(COPY "gudhi/weighted_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/dtm_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/hera/__init__.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/hera") + file(COPY "gudhi/datasets/generators/points/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/datasets/generators/points/" FILES_MATCHING PATTERN "*.py") + # Some files for pip package file(COPY "introduction.rst" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/") diff --git a/src/python/gudhi/datasets/generators/points/__init__.py b/src/python/gudhi/datasets/generators/points/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/python/gudhi/datasets/generators/points/_torus.cc b/src/python/gudhi/datasets/generators/points/_torus.cc new file mode 100644 index 00000000..21638bb8 --- /dev/null +++ b/src/python/gudhi/datasets/generators/points/_torus.cc @@ -0,0 +1,70 @@ +/* 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): Hind Montassif + * + * Copyright (C) 2021 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include + +#include +#include + +#include + +namespace py = pybind11; + + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern; + + +py::array_t generate_points_on_torus(size_t num_points, int dim, bool uniform) { + + std::vector points_generated; + + { + py::gil_scoped_release release; + points_generated = Gudhi::generate_points_on_torus_d(num_points, dim, uniform); + } + + size_t npoints = points_generated.size(); + + py::print("points generated size: "); + py::print(points_generated.size()); + py::print(points_generated[0].size()); + + GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double ambient space dimension"); + + py::array_t points({npoints, (size_t)2*dim}); + + py::buffer_info buf = points.request(); + double *ptr = static_cast(buf.ptr); + + for (size_t i = 0; i < npoints; i++) + for (int j = 0; j < 2*dim; j++) + ptr[i*(2*dim)+j] = points_generated[i][j]; + + return points; +} + +PYBIND11_MODULE(_torus, m) { + m.attr("__license__") = "LGPL v3"; + m.def("generate_random_points", &generate_points_on_torus, + py::arg("num_points"), py::arg("dim"), py::arg("uniform") = false, + R"pbdoc( + Generate random i.i.d. points on a d-torus in R^2d + + :param num_points: The number of points to be generated. + :type num_points: unsigned integer + :param dim: The dimension. + :type dim: integer + :param uniform: A flag to define if the points generation is uniform (generated as a grid). + :type uniform: bool + :rtype: numpy array of float + :returns: the generated points on a torus. + )pbdoc"); +} diff --git a/src/python/gudhi/datasets/generators/points/torus.py b/src/python/gudhi/datasets/generators/points/torus.py new file mode 100644 index 00000000..2de696b2 --- /dev/null +++ b/src/python/gudhi/datasets/generators/points/torus.py @@ -0,0 +1,52 @@ +# 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): Hind Montassif +# +# Copyright (C) 2021 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + +import numpy as np +import math + + +def generate_random_points(num_points, dim): + + # Generate random angles of size num_points*dim + alpha = 2*math.pi*np.random.rand(num_points*dim) + + # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points, 2*dim) + + return array_points + + +def generate_grid_points(num_points, dim): + + num_points_grid = (int(num_points**(1./dim)))**dim + + alpha = 2*math.pi*np.random.rand(num_points_grid*dim) + + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points_grid, 2*dim) + + return array_points + +def generate_points(num_points, dim, sample='random'): + if sample == 'random': + print("Sample is random") + npoints = num_points + elif sample == 'grid': + print("Sample is grid") + npoints = (int(num_points**(1./dim)))**dim + else: + print("Sample type '{}' is not supported".format(sample)) + return + + # Generate random angles of size num_points*dim + alpha = 2*math.pi*np.random.rand(npoints*dim) + + # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(npoints, 2*dim) + + return array_points -- cgit v1.2.3 From 5c140bbdae08561ce69f0cc05841eb1467aa8eab Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Fri, 7 May 2021 15:11:24 +0200 Subject: Use PI constant from numpy instead of math Modify grid points generation incorrect formula --- .../gudhi/datasets/generators/points/torus.py | 30 ++++++++-------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/python/gudhi/datasets/generators/points/torus.py b/src/python/gudhi/datasets/generators/points/torus.py index 2de696b2..5a2b9016 100644 --- a/src/python/gudhi/datasets/generators/points/torus.py +++ b/src/python/gudhi/datasets/generators/points/torus.py @@ -8,45 +8,35 @@ # - YYYY/MM Author: Description of the modification import numpy as np -import math - +import itertools def generate_random_points(num_points, dim): # Generate random angles of size num_points*dim - alpha = 2*math.pi*np.random.rand(num_points*dim) + alpha = 2*np.pi*np.random.rand(num_points*dim) - # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array - array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points, 2*dim) + # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + array_points = np.column_stack([np.cos(alpha), np.sin(alpha)]).reshape(-1, 2*dim) return array_points - def generate_grid_points(num_points, dim): - num_points_grid = (int(num_points**(1./dim)))**dim + num_points_grid = int(num_points**(1./dim)) + alpha = np.linspace(0, 2*np.pi, num_points_grid, endpoint=False) - alpha = 2*math.pi*np.random.rand(num_points_grid*dim) - - array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points_grid, 2*dim) + array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) + array_points = np.array(list(itertools.product(array_points_inter, repeat=dim))).reshape(-1, 2*dim) return array_points def generate_points(num_points, dim, sample='random'): if sample == 'random': print("Sample is random") - npoints = num_points + generate_random_points(num_points, dim) elif sample == 'grid': print("Sample is grid") - npoints = (int(num_points**(1./dim)))**dim + generate_grid_points(num_points, dim) else: print("Sample type '{}' is not supported".format(sample)) return - - # Generate random angles of size num_points*dim - alpha = 2*math.pi*np.random.rand(npoints*dim) - - # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array - array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(npoints, 2*dim) - - return array_points -- cgit v1.2.3 From a1497289e6808d247f3b2be69b97dc9053e2b4d1 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Fri, 7 May 2021 15:30:08 +0200 Subject: Replace num_points with n_samples to be consistent with sphere --- .../gudhi/datasets/generators/points/_torus.cc | 18 +++++++----------- src/python/gudhi/datasets/generators/points/torus.py | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/python/gudhi/datasets/generators/points/_torus.cc b/src/python/gudhi/datasets/generators/points/_torus.cc index 21638bb8..f4b4f14e 100644 --- a/src/python/gudhi/datasets/generators/points/_torus.cc +++ b/src/python/gudhi/datasets/generators/points/_torus.cc @@ -22,22 +22,18 @@ namespace py = pybind11; typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern; -py::array_t generate_points_on_torus(size_t num_points, int dim, bool uniform) { +py::array_t generate_points_on_torus(size_t n_samples, int dim, bool uniform) { std::vector points_generated; { py::gil_scoped_release release; - points_generated = Gudhi::generate_points_on_torus_d(num_points, dim, uniform); + points_generated = Gudhi::generate_points_on_torus_d(n_samples, dim, uniform); } size_t npoints = points_generated.size(); - py::print("points generated size: "); - py::print(points_generated.size()); - py::print(points_generated[0].size()); - - GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double ambient space dimension"); + GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double torus dimension"); py::array_t points({npoints, (size_t)2*dim}); @@ -54,15 +50,15 @@ py::array_t generate_points_on_torus(size_t num_points, int dim, bool un PYBIND11_MODULE(_torus, m) { m.attr("__license__") = "LGPL v3"; m.def("generate_random_points", &generate_points_on_torus, - py::arg("num_points"), py::arg("dim"), py::arg("uniform") = false, + py::arg("n_samples"), py::arg("dim"), py::arg("uniform") = false, R"pbdoc( Generate random i.i.d. points on a d-torus in R^2d - :param num_points: The number of points to be generated. - :type num_points: unsigned integer + :param n_samples: The number of points to be generated. + :type n_samples: integer :param dim: The dimension. :type dim: integer - :param uniform: A flag to define if the points generation is uniform (generated as a grid). + :param uniform: A flag to define if the points generation is uniform (i.e generated as a grid). :type uniform: bool :rtype: numpy array of float :returns: the generated points on a torus. diff --git a/src/python/gudhi/datasets/generators/points/torus.py b/src/python/gudhi/datasets/generators/points/torus.py index 5a2b9016..1df0a930 100644 --- a/src/python/gudhi/datasets/generators/points/torus.py +++ b/src/python/gudhi/datasets/generators/points/torus.py @@ -10,33 +10,33 @@ import numpy as np import itertools -def generate_random_points(num_points, dim): +def generate_random_points(n_samples, dim): - # Generate random angles of size num_points*dim - alpha = 2*np.pi*np.random.rand(num_points*dim) + # Generate random angles of size n_samples*dim + alpha = 2*np.pi*np.random.rand(n_samples*dim) - # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + # Based on angles, construct points of size n_samples*dim on a circle and reshape the result in a n_samples*2*dim array array_points = np.column_stack([np.cos(alpha), np.sin(alpha)]).reshape(-1, 2*dim) return array_points -def generate_grid_points(num_points, dim): +def generate_grid_points(n_samples, dim): - num_points_grid = int(num_points**(1./dim)) - alpha = np.linspace(0, 2*np.pi, num_points_grid, endpoint=False) + n_samples_grid = int(n_samples**(1./dim)) + alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) array_points = np.array(list(itertools.product(array_points_inter, repeat=dim))).reshape(-1, 2*dim) return array_points -def generate_points(num_points, dim, sample='random'): +def generate_points(n_samples, dim, sample='random'): if sample == 'random': print("Sample is random") - generate_random_points(num_points, dim) + generate_random_points(n_samples, dim) elif sample == 'grid': print("Sample is grid") - generate_grid_points(num_points, dim) + generate_grid_points(n_samples, dim) else: print("Sample type '{}' is not supported".format(sample)) return -- cgit v1.2.3 From 303b014508f849d8cb8a4369430068f54fa74c46 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Mon, 10 May 2021 10:27:57 +0200 Subject: Add __init__.py files at every module level Standardize functions to match the existing ones in sphere --- src/python/CMakeLists.txt | 6 +- src/python/gudhi/datasets/__init__.py | 0 src/python/gudhi/datasets/generators/__init__.py | 0 src/python/gudhi/datasets/generators/_points.cc | 66 ++++++++++++++++++++++ src/python/gudhi/datasets/generators/points.py | 42 ++++++++++++++ .../gudhi/datasets/generators/points/__init__.py | 0 .../gudhi/datasets/generators/points/_torus.cc | 66 ---------------------- .../gudhi/datasets/generators/points/torus.py | 42 -------------- 8 files changed, 111 insertions(+), 111 deletions(-) create mode 100644 src/python/gudhi/datasets/__init__.py create mode 100644 src/python/gudhi/datasets/generators/__init__.py create mode 100644 src/python/gudhi/datasets/generators/_points.cc create mode 100644 src/python/gudhi/datasets/generators/points.py delete mode 100644 src/python/gudhi/datasets/generators/points/__init__.py delete mode 100644 src/python/gudhi/datasets/generators/points/_torus.cc delete mode 100644 src/python/gudhi/datasets/generators/points/torus.py (limited to 'src') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 1b9db2b5..e146fedc 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -46,7 +46,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'clustering', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets/generators/points', ") + set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets', ") endif() if(CYTHON_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ") @@ -152,7 +152,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/wasserstein', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/bottleneck', ") if (NOT CGAL_VERSION VERSION_LESS 4.11.0) - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/points/_torus', ") + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/_points', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'bottleneck', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") endif () @@ -264,7 +264,7 @@ if(PYTHONINTERP_FOUND) file(COPY "gudhi/weighted_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/dtm_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/hera/__init__.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/hera") - file(COPY "gudhi/datasets/generators/points/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/datasets/generators/points/" FILES_MATCHING PATTERN "*.py") + file(COPY "gudhi/datasets" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi" FILES_MATCHING PATTERN "*.py") # Some files for pip package diff --git a/src/python/gudhi/datasets/__init__.py b/src/python/gudhi/datasets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/python/gudhi/datasets/generators/__init__.py b/src/python/gudhi/datasets/generators/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc new file mode 100644 index 00000000..561fd6d8 --- /dev/null +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -0,0 +1,66 @@ +/* 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): Hind Montassif + * + * Copyright (C) 2021 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include + +#include +#include + +#include + +namespace py = pybind11; + + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern; + + +py::array_t generate_points_on_torus(size_t n_samples, int dim, bool uniform) { + + std::vector points_generated; + + { + py::gil_scoped_release release; + points_generated = Gudhi::generate_points_on_torus_d(n_samples, dim, uniform); + } + + size_t npoints = points_generated.size(); + + GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double torus dimension"); + + py::array_t points({npoints, (size_t)2*dim}); + + py::buffer_info buf = points.request(); + double *ptr = static_cast(buf.ptr); + + for (size_t i = 0; i < npoints; i++) + for (int j = 0; j < 2*dim; j++) + ptr[i*(2*dim)+j] = points_generated[i][j]; + + return points; +} + +PYBIND11_MODULE(_points, m) { + m.attr("__license__") = "LGPL v3"; + m.def("torus", &generate_points_on_torus, + py::arg("n_samples"), py::arg("dim"), py::arg("uniform") = false, + R"pbdoc( + Generate random i.i.d. points on a d-torus in R^2d + + :param n_samples: The number of points to be generated. + :type n_samples: integer + :param dim: The dimension. + :type dim: integer + :param uniform: A flag to define if the points generation is uniform (i.e generated as a grid). + :type uniform: bool + :rtype: numpy array of float + :returns: the generated points on a torus. + )pbdoc"); +} diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py new file mode 100644 index 00000000..d5a370ad --- /dev/null +++ b/src/python/gudhi/datasets/generators/points.py @@ -0,0 +1,42 @@ +# 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): Hind Montassif +# +# Copyright (C) 2021 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + +import numpy as np +import itertools + +def _generate_random_points(n_samples, dim): + + # Generate random angles of size n_samples*dim + alpha = 2*np.pi*np.random.rand(n_samples*dim) + + # Based on angles, construct points of size n_samples*dim on a circle and reshape the result in a n_samples*2*dim array + array_points = np.column_stack([np.cos(alpha), np.sin(alpha)]).reshape(-1, 2*dim) + + return array_points + +def _generate_grid_points(n_samples, dim): + + n_samples_grid = int(n_samples**(1./dim)) + alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) + + array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) + array_points = np.array(list(itertools.product(array_points_inter, repeat=dim))).reshape(-1, 2*dim) + + return array_points + +def torus(n_samples, dim, sample='random'): + if sample == 'random': + print("Sample is random") + return _generate_random_points(n_samples, dim) + elif sample == 'grid': + print("Sample is grid") + return _generate_grid_points(n_samples, dim) + else: + raise Exception("Sample type '{}' is not supported".format(sample)) + return diff --git a/src/python/gudhi/datasets/generators/points/__init__.py b/src/python/gudhi/datasets/generators/points/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/python/gudhi/datasets/generators/points/_torus.cc b/src/python/gudhi/datasets/generators/points/_torus.cc deleted file mode 100644 index f4b4f14e..00000000 --- a/src/python/gudhi/datasets/generators/points/_torus.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* 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): Hind Montassif - * - * Copyright (C) 2021 Inria - * - * Modification(s): - * - YYYY/MM Author: Description of the modification - */ - -#include -#include - -#include -#include - -#include - -namespace py = pybind11; - - -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern; - - -py::array_t generate_points_on_torus(size_t n_samples, int dim, bool uniform) { - - std::vector points_generated; - - { - py::gil_scoped_release release; - points_generated = Gudhi::generate_points_on_torus_d(n_samples, dim, uniform); - } - - size_t npoints = points_generated.size(); - - GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double torus dimension"); - - py::array_t points({npoints, (size_t)2*dim}); - - py::buffer_info buf = points.request(); - double *ptr = static_cast(buf.ptr); - - for (size_t i = 0; i < npoints; i++) - for (int j = 0; j < 2*dim; j++) - ptr[i*(2*dim)+j] = points_generated[i][j]; - - return points; -} - -PYBIND11_MODULE(_torus, m) { - m.attr("__license__") = "LGPL v3"; - m.def("generate_random_points", &generate_points_on_torus, - py::arg("n_samples"), py::arg("dim"), py::arg("uniform") = false, - R"pbdoc( - Generate random i.i.d. points on a d-torus in R^2d - - :param n_samples: The number of points to be generated. - :type n_samples: integer - :param dim: The dimension. - :type dim: integer - :param uniform: A flag to define if the points generation is uniform (i.e generated as a grid). - :type uniform: bool - :rtype: numpy array of float - :returns: the generated points on a torus. - )pbdoc"); -} diff --git a/src/python/gudhi/datasets/generators/points/torus.py b/src/python/gudhi/datasets/generators/points/torus.py deleted file mode 100644 index 1df0a930..00000000 --- a/src/python/gudhi/datasets/generators/points/torus.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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): Hind Montassif -# -# Copyright (C) 2021 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - -import numpy as np -import itertools - -def generate_random_points(n_samples, dim): - - # Generate random angles of size n_samples*dim - alpha = 2*np.pi*np.random.rand(n_samples*dim) - - # Based on angles, construct points of size n_samples*dim on a circle and reshape the result in a n_samples*2*dim array - array_points = np.column_stack([np.cos(alpha), np.sin(alpha)]).reshape(-1, 2*dim) - - return array_points - -def generate_grid_points(n_samples, dim): - - n_samples_grid = int(n_samples**(1./dim)) - alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) - - array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) - array_points = np.array(list(itertools.product(array_points_inter, repeat=dim))).reshape(-1, 2*dim) - - return array_points - -def generate_points(n_samples, dim, sample='random'): - if sample == 'random': - print("Sample is random") - generate_random_points(n_samples, dim) - elif sample == 'grid': - print("Sample is grid") - generate_grid_points(n_samples, dim) - else: - print("Sample type '{}' is not supported".format(sample)) - return -- cgit v1.2.3 From 0b238a336f15128d777252cd084ee996491e6882 Mon Sep 17 00:00:00 2001 From: Hind-M Date: Thu, 27 May 2021 09:56:02 +0200 Subject: Add documentation to python torus fonction and apply some modifications according to PR comments --- src/python/gudhi/datasets/generators/_points.cc | 2 +- src/python/gudhi/datasets/generators/points.py | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 561fd6d8..003b65a3 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -56,7 +56,7 @@ PYBIND11_MODULE(_points, m) { :param n_samples: The number of points to be generated. :type n_samples: integer - :param dim: The dimension. + :param dim: The dimension of the torus on which points would be generated in R^2*dim. :type dim: integer :param uniform: A flag to define if the points generation is uniform (i.e generated as a grid). :type uniform: bool diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index d5a370ad..a8f5ad54 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -10,7 +10,7 @@ import numpy as np import itertools -def _generate_random_points(n_samples, dim): +def _generate_random_points_on_torus(n_samples, dim): # Generate random angles of size n_samples*dim alpha = 2*np.pi*np.random.rand(n_samples*dim) @@ -20,8 +20,9 @@ def _generate_random_points(n_samples, dim): return array_points -def _generate_grid_points(n_samples, dim): +def _generate_grid_points_on_torus(n_samples, dim): + # Generate points on a dim-torus as a grid n_samples_grid = int(n_samples**(1./dim)) alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) @@ -31,12 +32,25 @@ def _generate_grid_points(n_samples, dim): return array_points def torus(n_samples, dim, sample='random'): + ''' + Generate points on a dim-torus in R^2dim either randomly or on a grid + + :param n_samples: The number of points to be generated. + :param dim: The dimension of the torus on which points would be generated in R^2*dim. + :param sample: The sample type of the generated points. Can be 'random' or 'grid'. + :returns: numpy array containing the generated points on a torus. + The shape of returned numpy array is : + if sample is 'random' : (n_samples, 2*dim) + if sample is 'grid' : ((int(n_samples**(1./dim)))**dim, 2*dim) + ''' if sample == 'random': + # Generate points randomly print("Sample is random") - return _generate_random_points(n_samples, dim) + return _generate_random_points_on_torus(n_samples, dim) elif sample == 'grid': + # Generate points on a grid print("Sample is grid") - return _generate_grid_points(n_samples, dim) + return _generate_grid_points_on_torus(n_samples, dim) else: - raise Exception("Sample type '{}' is not supported".format(sample)) + raise ValueError("Sample type '{}' is not supported".format(sample)) return -- cgit v1.2.3 From 09214d0ad3abd0c81b3a2c8051bf8b370350d6e5 Mon Sep 17 00:00:00 2001 From: Hind-M Date: Tue, 1 Jun 2021 11:20:26 +0200 Subject: Add datasets generators documentation --- src/python/doc/datasets_generators.inc | 14 ++++ src/python/doc/datasets_generators.rst | 97 ++++++++++++++++++++++++++ src/python/doc/examples.rst | 1 + src/python/doc/index.rst | 5 ++ src/python/gudhi/datasets/generators/points.py | 10 +-- 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 src/python/doc/datasets_generators.inc create mode 100644 src/python/doc/datasets_generators.rst (limited to 'src') diff --git a/src/python/doc/datasets_generators.inc b/src/python/doc/datasets_generators.inc new file mode 100644 index 00000000..c88115c3 --- /dev/null +++ b/src/python/doc/datasets_generators.inc @@ -0,0 +1,14 @@ +.. table:: + :widths: 30 40 30 + + +-----------------------------------+--------------------------------------------+--------------------------------------------------------------------------------------+ + | | :math:`(x_1, x_2, \ldots, x_d)` | Datasets generators (points). | :Authors: Hind Montassif | + | | | | + | | | :Since: GUDHI 3.5.0 | + | | | | + | | | :License: MIT (`LGPL v3 `_) | + | | | | + | | | :Requires: `CGAL `_ | + +-----------------------------------+--------------------------------------------+--------------------------------------------------------------------------------------+ + | * :doc:`datasets_generators` | + +-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst new file mode 100644 index 00000000..ef21c9d2 --- /dev/null +++ b/src/python/doc/datasets_generators.rst @@ -0,0 +1,97 @@ + +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + +=========================== +Datasets generators manual +=========================== + +We provide the generation of different customizable datasets to use as inputs for Gudhi complexes and data structures. + + +Points generators +------------------ + +Points on sphere +^^^^^^^^^^^^^^^^ + +The module **_points** enables the generation of random i.i.d. points uniformly on a (d-1)-sphere in :math:`R^d`. +The user should provide the number of points to be generated on the sphere :code:`n_samples` and the ambient dimension :code:`ambient_dim`. +The :code:`radius` of sphere is optional and is equal to **1** by default. +Only random points generation is currently available. + +The generated points are given as an array of shape :math:`(n\_samples, ambient\_dim)`. + +Example +""""""" + +.. code-block:: python + + from gudhi.datasets.generators import _points + from gudhi import AlphaComplex + + # Generate 50 points on a sphere in R^2 + gen_points = _points.sphere(n_samples = 50, ambient_dim = 2, radius = 1, sample = "random") + + # Create an alpha complex from the generated points + alpha_complex = AlphaComplex(points = gen_points) + +.. autofunction:: gudhi.datasets.generators._points.sphere + +Points on torus +^^^^^^^^^^^^^^^^ + +You can also generate points on a torus. + +Two modules are available and give the same output: the first one depends on **CGAL** and the second does not and consists of full python code. + +On another hand, two sample types are provided : you can either generate i.i.d. points on a d-torus in :math:`R^{2d}` *randomly* or on a *grid*. + +First module : **_points** +"""""""""""""""""""""""""" + +The user should provide the number of points to be generated on the torus :code:`n_samples`, and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. +The flag :code:`uniform` is optional and is set to **False** by default, meaning that the points will be generated randomly. +In this case, the returned generated points would be an array of shape :math:`(n\_samples, 2*dim)`. +Otherwise, if set to **True**, the points are generated as a grid and would be given as an array of shape : + +.. math:: + + ( [n\_samples^{1 \over {dim}}]^{dim}, 2*dim ) + +Example +""""""" +.. code-block:: python + + from gudhi.datasets.generators import _points + + # Generate 50 points randomly on a torus in R^6 + gen_points = _points.torus(n_samples = 50, dim = 3) + + # Generate 27 points on a torus as a grid in R^6 + gen_points = _points.torus(n_samples = 50, dim = 3, uniform = True) + +.. autofunction:: gudhi.datasets.generators._points.torus + +Second module : **points** +"""""""""""""""""""""""""" + +The user should provide the number of points to be generated on the torus :code:`n_samples` and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. +The :code:`sample` argument is optional and is set to **'random'** by default. +The other allowed value of sample type is **'grid'** and is equivalent to :code:`uniform = True` in the first module. + +Example +""""""" +.. code-block:: python + + from gudhi.datasets.generators import points + + # Generate 50 points randomly on a torus in R^6 + gen_points = points.torus(n_samples = 50, dim = 3) + + # Generate 27 points on a torus as a grid in R^6 + gen_points = points.torus(n_samples = 50, dim = 3, sample = 'grid') + + +.. autofunction:: gudhi.datasets.generators.points.torus diff --git a/src/python/doc/examples.rst b/src/python/doc/examples.rst index 76e5d4c7..1442f185 100644 --- a/src/python/doc/examples.rst +++ b/src/python/doc/examples.rst @@ -8,6 +8,7 @@ Examples .. only:: builder_html * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`alpha_complex_from_generated_points_on_sphere_example.py <../example/alpha_complex_from_generated_points_on_sphere_example.py>` * :download:`alpha_complex_from_points_example.py <../example/alpha_complex_from_points_example.py>` * :download:`alpha_rips_persistence_bottleneck_distance.py <../example/alpha_rips_persistence_bottleneck_distance.py>` * :download:`bottleneck_basic_example.py <../example/bottleneck_basic_example.py>` diff --git a/src/python/doc/index.rst b/src/python/doc/index.rst index 040e57a4..2d7921ae 100644 --- a/src/python/doc/index.rst +++ b/src/python/doc/index.rst @@ -91,3 +91,8 @@ Clustering ********** .. include:: clustering.inc + +Datasets generators +******************* + +.. include:: datasets_generators.inc diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index a8f5ad54..3870dea6 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -32,17 +32,17 @@ def _generate_grid_points_on_torus(n_samples, dim): return array_points def torus(n_samples, dim, sample='random'): - ''' + """ Generate points on a dim-torus in R^2dim either randomly or on a grid :param n_samples: The number of points to be generated. :param dim: The dimension of the torus on which points would be generated in R^2*dim. :param sample: The sample type of the generated points. Can be 'random' or 'grid'. :returns: numpy array containing the generated points on a torus. - The shape of returned numpy array is : - if sample is 'random' : (n_samples, 2*dim) - if sample is 'grid' : ((int(n_samples**(1./dim)))**dim, 2*dim) - ''' + The shape of returned numpy array is : + if sample is 'random' : (n_samples, 2*dim). + if sample is 'grid' : ([n_samples**(1./dim)]**dim, 2*dim). + """ if sample == 'random': # Generate points randomly print("Sample is random") -- cgit v1.2.3 From b04759faf8f474ff98e9e229c41d85ff3bf009da Mon Sep 17 00:00:00 2001 From: Hind-M Date: Mon, 7 Jun 2021 11:56:48 +0200 Subject: Add a 3d sphere image to doc for datasets_generators --- src/python/doc/datasets_generators.inc | 4 ++-- src/python/doc/img/sphere_3d.png | Bin 0 -> 90550 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 src/python/doc/img/sphere_3d.png (limited to 'src') diff --git a/src/python/doc/datasets_generators.inc b/src/python/doc/datasets_generators.inc index c88115c3..8d169275 100644 --- a/src/python/doc/datasets_generators.inc +++ b/src/python/doc/datasets_generators.inc @@ -2,8 +2,8 @@ :widths: 30 40 30 +-----------------------------------+--------------------------------------------+--------------------------------------------------------------------------------------+ - | | :math:`(x_1, x_2, \ldots, x_d)` | Datasets generators (points). | :Authors: Hind Montassif | - | | | | + | .. figure:: | Datasets generators (points). | :Authors: Hind Montassif | + | img/sphere_3d.png | | | | | | :Since: GUDHI 3.5.0 | | | | | | | | :License: MIT (`LGPL v3 `_) | diff --git a/src/python/doc/img/sphere_3d.png b/src/python/doc/img/sphere_3d.png new file mode 100644 index 00000000..7e7f0ab2 Binary files /dev/null and b/src/python/doc/img/sphere_3d.png differ -- cgit v1.2.3 From b9160fb8410bbb999913b0b4e91f1aa1ff58d2cd Mon Sep 17 00:00:00 2001 From: Hind-M Date: Mon, 7 Jun 2021 17:07:55 +0200 Subject: Replace 'uniform' flag of torus generation with 'sample' taking two possible values: 'grid'(i.e uniform==True) or 'random' (i.e uniform==False) --- src/Tangential_complex/benchmark/benchmark_tc.cpp | 2 +- src/common/include/gudhi/random_point_generators.h | 10 +++++----- src/common/utilities/off_file_from_shape_generator.cpp | 2 +- src/python/doc/datasets_generators.rst | 8 ++++---- src/python/gudhi/datasets/generators/_points.cc | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/Tangential_complex/benchmark/benchmark_tc.cpp b/src/Tangential_complex/benchmark/benchmark_tc.cpp index e3b2a04f..6da1425f 100644 --- a/src/Tangential_complex/benchmark/benchmark_tc.cpp +++ b/src/Tangential_complex/benchmark/benchmark_tc.cpp @@ -704,7 +704,7 @@ int main() { points = Gudhi::generate_points_on_torus_d( num_points, intrinsic_dim, - param1 == "Y", // uniform + (param1 == "Y") ? "grid" : "random", // grid or random sample type std::atof(param2.c_str())); // radius_noise_percentage } else if (input == "generate_klein_bottle_3D") { points = Gudhi::generate_points_on_klein_bottle_3D( diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h index 33fb182d..07e4f3da 100644 --- a/src/common/include/gudhi/random_point_generators.h +++ b/src/common/include/gudhi/random_point_generators.h @@ -185,7 +185,7 @@ std::vector generate_points_on_torus_3D(std::size_t nu // "Private" function used by generate_points_on_torus_d template -static void generate_uniform_points_on_torus_d(const Kernel &k, int dim, std::size_t num_slices, +static void generate_grid_points_on_torus_d(const Kernel &k, int dim, std::size_t num_slices, OutputIterator out, double radius_noise_percentage = 0., std::vector current_point = @@ -208,14 +208,14 @@ static void generate_uniform_points_on_torus_d(const Kernel &k, int dim, std::si double alpha = two_pi * slice_idx / num_slices; cp2.push_back(radius_noise_ratio * std::cos(alpha)); cp2.push_back(radius_noise_ratio * std::sin(alpha)); - generate_uniform_points_on_torus_d( + generate_grid_points_on_torus_d( k, dim, num_slices, out, radius_noise_percentage, cp2); } } } template -std::vector generate_points_on_torus_d(std::size_t num_points, int dim, bool uniform = false, +std::vector generate_points_on_torus_d(std::size_t num_points, int dim, std::string sample = "random", double radius_noise_percentage = 0.) { using namespace boost::math::double_constants; @@ -226,9 +226,9 @@ std::vector generate_points_on_torus_d(std::size_t num std::vector points; points.reserve(num_points); - if (uniform) { + if (sample == "grid") { std::size_t num_slices = (std::size_t)std::pow(num_points, 1. / dim); - generate_uniform_points_on_torus_d( + generate_grid_points_on_torus_d( k, dim, num_slices, std::back_inserter(points), radius_noise_percentage); } else { for (std::size_t i = 0; i < num_points;) { diff --git a/src/common/utilities/off_file_from_shape_generator.cpp b/src/common/utilities/off_file_from_shape_generator.cpp index 6efef4fc..71ede434 100644 --- a/src/common/utilities/off_file_from_shape_generator.cpp +++ b/src/common/utilities/off_file_from_shape_generator.cpp @@ -135,7 +135,7 @@ int main(int argc, char **argv) { if (dimension == 3) points = Gudhi::generate_points_on_torus_3D(points_number, dimension, radius, radius/2.); else - points = Gudhi::generate_points_on_torus_d(points_number, dimension, true); + points = Gudhi::generate_points_on_torus_d(points_number, dimension, "grid"); break; case Data_shape::klein: switch (dimension) { diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst index ef21c9d2..2802eccd 100644 --- a/src/python/doc/datasets_generators.rst +++ b/src/python/doc/datasets_generators.rst @@ -52,9 +52,9 @@ First module : **_points** """""""""""""""""""""""""" The user should provide the number of points to be generated on the torus :code:`n_samples`, and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. -The flag :code:`uniform` is optional and is set to **False** by default, meaning that the points will be generated randomly. +The :code:`sample` argument is optional and is set to **'random'** by default. In this case, the returned generated points would be an array of shape :math:`(n\_samples, 2*dim)`. -Otherwise, if set to **True**, the points are generated as a grid and would be given as an array of shape : +Otherwise, if set to **'grid'**, the points are generated on a grid and would be given as an array of shape : .. math:: @@ -70,7 +70,7 @@ Example gen_points = _points.torus(n_samples = 50, dim = 3) # Generate 27 points on a torus as a grid in R^6 - gen_points = _points.torus(n_samples = 50, dim = 3, uniform = True) + gen_points = _points.torus(n_samples = 50, dim = 3, sample = 'grid') .. autofunction:: gudhi.datasets.generators._points.torus @@ -79,7 +79,7 @@ Second module : **points** The user should provide the number of points to be generated on the torus :code:`n_samples` and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. The :code:`sample` argument is optional and is set to **'random'** by default. -The other allowed value of sample type is **'grid'** and is equivalent to :code:`uniform = True` in the first module. +The other allowed value of sample type is **'grid'**. Example """"""" diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 55b21b2b..6bbdf284 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -46,13 +46,13 @@ py::array_t generate_points_on_sphere(size_t n_samples, int ambient_dim, return points; } -py::array_t generate_points_on_torus(size_t n_samples, int dim, bool uniform) { +py::array_t generate_points_on_torus(size_t n_samples, int dim, std::string sample) { std::vector points_generated; { py::gil_scoped_release release; - points_generated = Gudhi::generate_points_on_torus_d(n_samples, dim, uniform); + points_generated = Gudhi::generate_points_on_torus_d(n_samples, dim, sample); } size_t npoints = points_generated.size(); @@ -93,7 +93,7 @@ PYBIND11_MODULE(_points, m) { )pbdoc"); m.def("torus", &generate_points_on_torus, - py::arg("n_samples"), py::arg("dim"), py::arg("uniform") = false, + py::arg("n_samples"), py::arg("dim"), py::arg("sample") = "random", R"pbdoc( Generate random i.i.d. points on a d-torus in R^2d @@ -101,8 +101,8 @@ PYBIND11_MODULE(_points, m) { :type n_samples: integer :param dim: The dimension of the torus on which points would be generated in R^2*dim. :type dim: integer - :param uniform: A flag to define if the points generation is uniform (i.e generated as a grid). - :type uniform: bool + :param sample: The sample type. Available values are: `"random"` and `"grid"`. Default value is `"random"`. + :type sample: string :rtype: numpy array of float :returns: the generated points on a torus. )pbdoc"); -- cgit v1.2.3 From 575beed582f9288d83a403f4f578731f172f7f5f Mon Sep 17 00:00:00 2001 From: Hind-M Date: Wed, 11 Aug 2021 14:35:25 +0200 Subject: Add test for sphere and torus Fix numerical approximations inconsistencies with dim fraction exponent when generating points as grid on torus Add notes in doc regarding the torus versions use cases --- src/common/include/gudhi/random_point_generators.h | 2 +- src/python/CMakeLists.txt | 3 ++ src/python/doc/datasets_generators.rst | 5 +++ src/python/gudhi/datasets/generators/_points.cc | 4 +++ src/python/gudhi/datasets/generators/points.py | 5 +-- src/python/test/test_datasets_generators.py | 40 ++++++++++++++++++++++ 6 files changed, 54 insertions(+), 5 deletions(-) create mode 100755 src/python/test/test_datasets_generators.py (limited to 'src') diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h index 07e4f3da..25a7392d 100644 --- a/src/common/include/gudhi/random_point_generators.h +++ b/src/common/include/gudhi/random_point_generators.h @@ -227,7 +227,7 @@ std::vector generate_points_on_torus_d(std::size_t num std::vector points; points.reserve(num_points); if (sample == "grid") { - std::size_t num_slices = (std::size_t)std::pow(num_points, 1. / dim); + std::size_t num_slices = (std::size_t)std::pow(num_points + .5, 1. / dim); // add .5 to avoid rounding down with numerical approximations generate_grid_points_on_torus_d( k, dim, num_slices, std::back_inserter(points), radius_noise_percentage); } else { diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 8c46004a..f30dfe6d 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -443,6 +443,9 @@ if(PYTHONINTERP_FOUND) # Euclidean witness add_gudhi_py_test(test_euclidean_witness_complex) + # Datasets generators + add_gudhi_py_test(test_datasets_generators) # TODO separate full python datasets generators in another test file independant from CGAL ? + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) # Cubical diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst index 2802eccd..e63dde82 100644 --- a/src/python/doc/datasets_generators.rst +++ b/src/python/doc/datasets_generators.rst @@ -60,6 +60,9 @@ Otherwise, if set to **'grid'**, the points are generated on a grid and would be ( [n\_samples^{1 \over {dim}}]^{dim}, 2*dim ) + +**Note:** This version is recommended when the user wishes to use **'grid'** as sample type, or **'random'** with a relatively small number of samples (~ less than 150). + Example """"""" .. code-block:: python @@ -81,6 +84,8 @@ The user should provide the number of points to be generated on the torus :code: The :code:`sample` argument is optional and is set to **'random'** by default. The other allowed value of sample type is **'grid'**. +**Note:** This version is recommended when the user wishes to use **'random'** as sample type with a great number of samples and a low dimension. + Example """"""" .. code-block:: python diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 6bbdf284..3d38ff90 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -48,6 +48,10 @@ py::array_t generate_points_on_sphere(size_t n_samples, int ambient_dim, py::array_t generate_points_on_torus(size_t n_samples, int dim, std::string sample) { + if ( (sample != "random") && (sample != "grid")) { + throw pybind11::value_error("This sample type is not supported"); + } + std::vector points_generated; { diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index 3870dea6..daada486 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -23,7 +23,7 @@ def _generate_random_points_on_torus(n_samples, dim): def _generate_grid_points_on_torus(n_samples, dim): # Generate points on a dim-torus as a grid - n_samples_grid = int(n_samples**(1./dim)) + n_samples_grid = int((n_samples+.5)**(1./dim)) # add .5 to avoid rounding down with numerical approximations alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) @@ -45,12 +45,9 @@ def torus(n_samples, dim, sample='random'): """ if sample == 'random': # Generate points randomly - print("Sample is random") return _generate_random_points_on_torus(n_samples, dim) elif sample == 'grid': # Generate points on a grid - print("Sample is grid") return _generate_grid_points_on_torus(n_samples, dim) else: raise ValueError("Sample type '{}' is not supported".format(sample)) - return diff --git a/src/python/test/test_datasets_generators.py b/src/python/test/test_datasets_generators.py new file mode 100755 index 00000000..656c30ee --- /dev/null +++ b/src/python/test/test_datasets_generators.py @@ -0,0 +1,40 @@ +""" 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): Hind Montassif + + Copyright (C) 2021 Inria + + Modification(s): + - YYYY/MM Author: Description of the modification +""" + +from gudhi.datasets.generators import points +from gudhi.datasets.generators import _points + +import pytest + +def test_sphere(): + assert _points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'random').shape == (10, 2) + + with pytest.raises(ValueError): + _points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'other') + +def test_torus(): + assert _points.torus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) + assert _points.torus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) + + assert _points.torus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) + assert _points.torus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) + + with pytest.raises(ValueError): + _points.torus(n_samples = 10, dim = 4, sample = 'other') + +def test_torus_full_python(): + assert points.torus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) + assert points.torus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) + + assert points.torus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) + assert points.torus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) + + with pytest.raises(ValueError): + points.torus(n_samples = 10, dim = 4, sample = 'other') -- cgit v1.2.3 From 65619d48af98680294bf41c4023e04ee94f2745d Mon Sep 17 00:00:00 2001 From: Hind-M Date: Wed, 22 Sep 2021 09:36:18 +0200 Subject: Replace the doc sphere image plotted with trisurf with another using scattered points --- src/python/doc/img/sphere_3d.png | Bin 90550 -> 529148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'src') diff --git a/src/python/doc/img/sphere_3d.png b/src/python/doc/img/sphere_3d.png index 7e7f0ab2..70f3184f 100644 Binary files a/src/python/doc/img/sphere_3d.png and b/src/python/doc/img/sphere_3d.png differ -- cgit v1.2.3 From e23ca84fadcc2c65fd8cf2d141be804bf18b2fd6 Mon Sep 17 00:00:00 2001 From: Hind-M Date: Wed, 22 Sep 2021 15:20:03 +0200 Subject: Rename function of torus cpp version and import it with sphere in points Change documentation accordingly --- src/python/doc/datasets_generators.rst | 28 +++++++++++++------------ src/python/gudhi/datasets/generators/_points.cc | 9 +++++--- src/python/gudhi/datasets/generators/points.py | 3 +++ src/python/test/test_datasets_generators.py | 15 +++++++------ 4 files changed, 31 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst index e63dde82..c0bbb973 100644 --- a/src/python/doc/datasets_generators.rst +++ b/src/python/doc/datasets_generators.rst @@ -13,10 +13,12 @@ We provide the generation of different customizable datasets to use as inputs fo Points generators ------------------ +The module **points** enables the generation of random points on a sphere, random points on a torus and as a grid. + Points on sphere ^^^^^^^^^^^^^^^^ -The module **_points** enables the generation of random i.i.d. points uniformly on a (d-1)-sphere in :math:`R^d`. +The function **sphere** enables the generation of random i.i.d. points uniformly on a (d-1)-sphere in :math:`R^d`. The user should provide the number of points to be generated on the sphere :code:`n_samples` and the ambient dimension :code:`ambient_dim`. The :code:`radius` of sphere is optional and is equal to **1** by default. Only random points generation is currently available. @@ -28,28 +30,28 @@ Example .. code-block:: python - from gudhi.datasets.generators import _points + from gudhi.datasets.generators import points from gudhi import AlphaComplex # Generate 50 points on a sphere in R^2 - gen_points = _points.sphere(n_samples = 50, ambient_dim = 2, radius = 1, sample = "random") + gen_points = points.sphere(n_samples = 50, ambient_dim = 2, radius = 1, sample = "random") # Create an alpha complex from the generated points alpha_complex = AlphaComplex(points = gen_points) -.. autofunction:: gudhi.datasets.generators._points.sphere +.. autofunction:: gudhi.datasets.generators.points.sphere Points on torus ^^^^^^^^^^^^^^^^ You can also generate points on a torus. -Two modules are available and give the same output: the first one depends on **CGAL** and the second does not and consists of full python code. +Two functions are available and give the same output: the first one depends on **CGAL** and the second does not and consists of full python code. On another hand, two sample types are provided : you can either generate i.i.d. points on a d-torus in :math:`R^{2d}` *randomly* or on a *grid*. -First module : **_points** -"""""""""""""""""""""""""" +First function : **ctorus** +""""""""""""""""""""""""""" The user should provide the number of points to be generated on the torus :code:`n_samples`, and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. The :code:`sample` argument is optional and is set to **'random'** by default. @@ -67,18 +69,18 @@ Example """"""" .. code-block:: python - from gudhi.datasets.generators import _points + from gudhi.datasets.generators import points # Generate 50 points randomly on a torus in R^6 - gen_points = _points.torus(n_samples = 50, dim = 3) + gen_points = points.ctorus(n_samples = 50, dim = 3) # Generate 27 points on a torus as a grid in R^6 - gen_points = _points.torus(n_samples = 50, dim = 3, sample = 'grid') + gen_points = points.ctorus(n_samples = 50, dim = 3, sample = 'grid') -.. autofunction:: gudhi.datasets.generators._points.torus +.. autofunction:: gudhi.datasets.generators.points.ctorus -Second module : **points** -"""""""""""""""""""""""""" +Second function : **torus** +""""""""""""""""""""""""""" The user should provide the number of points to be generated on the torus :code:`n_samples` and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. The :code:`sample` argument is optional and is set to **'random'** by default. diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 3d38ff90..536fa949 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -96,10 +96,10 @@ PYBIND11_MODULE(_points, m) { :returns: the generated points on a sphere. )pbdoc"); - m.def("torus", &generate_points_on_torus, + m.def("ctorus", &generate_points_on_torus, py::arg("n_samples"), py::arg("dim"), py::arg("sample") = "random", R"pbdoc( - Generate random i.i.d. points on a d-torus in R^2d + Generate random i.i.d. points on a d-torus in R^2d or as a grid :param n_samples: The number of points to be generated. :type n_samples: integer @@ -107,7 +107,10 @@ PYBIND11_MODULE(_points, m) { :type dim: integer :param sample: The sample type. Available values are: `"random"` and `"grid"`. Default value is `"random"`. :type sample: string - :rtype: numpy array of float + :rtype: numpy array of float. + The shape of returned numpy array is : + if sample is 'random' : (n_samples, 2*dim). + if sample is 'grid' : ([n_samples**(1./dim)]**dim, 2*dim). :returns: the generated points on a torus. )pbdoc"); } diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index daada486..1995f769 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -10,6 +10,9 @@ import numpy as np import itertools +from ._points import ctorus +from ._points import sphere + def _generate_random_points_on_torus(n_samples, dim): # Generate random angles of size n_samples*dim diff --git a/src/python/test/test_datasets_generators.py b/src/python/test/test_datasets_generators.py index 656c30ee..4c087c57 100755 --- a/src/python/test/test_datasets_generators.py +++ b/src/python/test/test_datasets_generators.py @@ -9,25 +9,24 @@ """ from gudhi.datasets.generators import points -from gudhi.datasets.generators import _points import pytest def test_sphere(): - assert _points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'random').shape == (10, 2) + assert points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'random').shape == (10, 2) with pytest.raises(ValueError): - _points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'other') + points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'other') def test_torus(): - assert _points.torus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) - assert _points.torus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) + assert points.ctorus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) + assert points.ctorus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) - assert _points.torus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) - assert _points.torus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) + assert points.ctorus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) + assert points.ctorus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) with pytest.raises(ValueError): - _points.torus(n_samples = 10, dim = 4, sample = 'other') + points.ctorus(n_samples = 10, dim = 4, sample = 'other') def test_torus_full_python(): assert points.torus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) -- cgit v1.2.3 From 36959807d5091b79aedabbc67c363dd761c9d5ee Mon Sep 17 00:00:00 2001 From: Hind-M Date: Thu, 21 Oct 2021 17:08:43 +0200 Subject: Factorize cpp and python torus tests implementations --- src/python/test/test_datasets_generators.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/python/test/test_datasets_generators.py b/src/python/test/test_datasets_generators.py index 4c087c57..e2d300e0 100755 --- a/src/python/test/test_datasets_generators.py +++ b/src/python/test/test_datasets_generators.py @@ -18,22 +18,16 @@ def test_sphere(): with pytest.raises(ValueError): points.sphere(n_samples = 10, ambient_dim = 2, radius = 1., sample = 'other') -def test_torus(): - assert points.ctorus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) - assert points.ctorus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) - - assert points.ctorus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) - assert points.ctorus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) - - with pytest.raises(ValueError): - points.ctorus(n_samples = 10, dim = 4, sample = 'other') +def _basic_torus(impl): + assert impl(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) + assert impl(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) -def test_torus_full_python(): - assert points.torus(n_samples = 64, dim = 3, sample = 'random').shape == (64, 6) - assert points.torus(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) - - assert points.torus(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) - assert points.torus(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) + assert impl(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) + assert impl(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) with pytest.raises(ValueError): - points.torus(n_samples = 10, dim = 4, sample = 'other') + impl(n_samples = 10, dim = 4, sample = 'other') + +def test_torus(): + for torus_impl in [points.torus, points.ctorus]: + _basic_torus(torus_impl) -- cgit v1.2.3 From bb8c4994b89fb6bfdd80b76912acadf6197f93cc Mon Sep 17 00:00:00 2001 From: Hind-M Date: Tue, 26 Oct 2021 13:59:44 +0200 Subject: Add comments and some minor changes following code review --- src/python/doc/datasets_generators.rst | 13 +++++++------ src/python/gudhi/datasets/generators/_points.cc | 2 +- src/python/gudhi/datasets/generators/points.py | 6 +++--- src/python/test/test_datasets_generators.py | 2 ++ 4 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst index c0bbb973..3700b8a2 100644 --- a/src/python/doc/datasets_generators.rst +++ b/src/python/doc/datasets_generators.rst @@ -48,22 +48,23 @@ You can also generate points on a torus. Two functions are available and give the same output: the first one depends on **CGAL** and the second does not and consists of full python code. -On another hand, two sample types are provided : you can either generate i.i.d. points on a d-torus in :math:`R^{2d}` *randomly* or on a *grid*. +On another hand, two sample types are provided: you can either generate i.i.d. points on a d-torus in :math:`R^{2d}` *randomly* or on a *grid*. -First function : **ctorus** +First function: **ctorus** """"""""""""""""""""""""""" The user should provide the number of points to be generated on the torus :code:`n_samples`, and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. The :code:`sample` argument is optional and is set to **'random'** by default. In this case, the returned generated points would be an array of shape :math:`(n\_samples, 2*dim)`. -Otherwise, if set to **'grid'**, the points are generated on a grid and would be given as an array of shape : +Otherwise, if set to **'grid'**, the points are generated on a grid and would be given as an array of shape: .. math:: - ( [n\_samples^{1 \over {dim}}]^{dim}, 2*dim ) + ( ⌊n\_samples^{1 \over {dim}}⌋^{dim}, 2*dim ) +**Note 1:** The output array first shape is rounded down to the closest perfect :math:`dim^{th}` power. -**Note:** This version is recommended when the user wishes to use **'grid'** as sample type, or **'random'** with a relatively small number of samples (~ less than 150). +**Note 2:** This version is recommended when the user wishes to use **'grid'** as sample type, or **'random'** with a relatively small number of samples (~ less than 150). Example """"""" @@ -79,7 +80,7 @@ Example .. autofunction:: gudhi.datasets.generators.points.ctorus -Second function : **torus** +Second function: **torus** """"""""""""""""""""""""""" The user should provide the number of points to be generated on the torus :code:`n_samples` and the dimension :code:`dim` of the torus on which points would be generated in :math:`R^{2dim}`. diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 536fa949..5d675930 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -110,7 +110,7 @@ PYBIND11_MODULE(_points, m) { :rtype: numpy array of float. The shape of returned numpy array is : if sample is 'random' : (n_samples, 2*dim). - if sample is 'grid' : ([n_samples**(1./dim)]**dim, 2*dim). + if sample is 'grid' : (⌊n_samples**(1./dim)⌋**dim, 2*dim), where shape[0] is rounded down to the closest perfect 'dim'th power. :returns: the generated points on a torus. )pbdoc"); } diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index 1995f769..7f4667af 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -36,15 +36,15 @@ def _generate_grid_points_on_torus(n_samples, dim): def torus(n_samples, dim, sample='random'): """ - Generate points on a dim-torus in R^2dim either randomly or on a grid + Generate points on a flat dim-torus in R^2dim either randomly or on a grid :param n_samples: The number of points to be generated. :param dim: The dimension of the torus on which points would be generated in R^2*dim. :param sample: The sample type of the generated points. Can be 'random' or 'grid'. :returns: numpy array containing the generated points on a torus. - The shape of returned numpy array is : + The shape of returned numpy array is: if sample is 'random' : (n_samples, 2*dim). - if sample is 'grid' : ([n_samples**(1./dim)]**dim, 2*dim). + if sample is 'grid' : (⌊n_samples**(1./dim)⌋**dim, 2*dim), where shape[0] is rounded down to the closest perfect 'dim'th power. """ if sample == 'random': # Generate points randomly diff --git a/src/python/test/test_datasets_generators.py b/src/python/test/test_datasets_generators.py index e2d300e0..933a763e 100755 --- a/src/python/test/test_datasets_generators.py +++ b/src/python/test/test_datasets_generators.py @@ -23,6 +23,8 @@ def _basic_torus(impl): assert impl(n_samples = 64, dim = 3, sample = 'grid').shape == (64, 6) assert impl(n_samples = 10, dim = 4, sample = 'random').shape == (10, 8) + + # Here 1**dim < n_samples < 2**dim, the output shape is therefore (1, 2*dim) = (1, 8), where shape[0] is rounded down to the closest perfect 'dim'th power assert impl(n_samples = 10, dim = 4, sample = 'grid').shape == (1, 8) with pytest.raises(ValueError): -- cgit v1.2.3 From 3a29558decccafe0b07dbf07d66f1410df6c187f Mon Sep 17 00:00:00 2001 From: Hind-M Date: Wed, 27 Oct 2021 09:58:52 +0200 Subject: Replace itertools in grid torus generation function with something faster in most general use cases --- src/python/gudhi/datasets/generators/points.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/python/gudhi/datasets/generators/points.py b/src/python/gudhi/datasets/generators/points.py index 7f4667af..cf97777d 100644 --- a/src/python/gudhi/datasets/generators/points.py +++ b/src/python/gudhi/datasets/generators/points.py @@ -8,7 +8,6 @@ # - YYYY/MM Author: Description of the modification import numpy as np -import itertools from ._points import ctorus from ._points import sphere @@ -29,10 +28,11 @@ def _generate_grid_points_on_torus(n_samples, dim): n_samples_grid = int((n_samples+.5)**(1./dim)) # add .5 to avoid rounding down with numerical approximations alpha = np.linspace(0, 2*np.pi, n_samples_grid, endpoint=False) - array_points_inter = np.column_stack([np.cos(alpha), np.sin(alpha)]) - array_points = np.array(list(itertools.product(array_points_inter, repeat=dim))).reshape(-1, 2*dim) - - return array_points + array_points = np.column_stack([np.cos(alpha), np.sin(alpha)]) + array_points_idx = np.empty([n_samples_grid]*dim + [dim], dtype=int) + for i, x in enumerate(np.ix_(*([np.arange(n_samples_grid)]*dim))): + array_points_idx[...,i] = x + return array_points[array_points_idx].reshape(-1, 2*dim) def torus(n_samples, dim, sample='random'): """ -- cgit v1.2.3 From 2ffbd4d63afd59b9d1995a7755db087b31f9c998 Mon Sep 17 00:00:00 2001 From: Hind-M Date: Wed, 27 Oct 2021 10:01:23 +0200 Subject: Add test to check outputs of the two torus implementations --- src/python/test/test_datasets_generators.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/python/test/test_datasets_generators.py b/src/python/test/test_datasets_generators.py index 933a763e..91ec4a65 100755 --- a/src/python/test/test_datasets_generators.py +++ b/src/python/test/test_datasets_generators.py @@ -33,3 +33,7 @@ def _basic_torus(impl): def test_torus(): for torus_impl in [points.torus, points.ctorus]: _basic_torus(torus_impl) + # Check that the two versions (torus and ctorus) generate the same output + assert points.ctorus(n_samples = 64, dim = 3, sample = 'random').all() == points.torus(n_samples = 64, dim = 3, sample = 'random').all() + assert points.ctorus(n_samples = 64, dim = 3, sample = 'grid').all() == points.torus(n_samples = 64, dim = 3, sample = 'grid').all() + assert points.ctorus(n_samples = 10, dim = 3, sample = 'grid').all() == points.torus(n_samples = 10, dim = 3, sample = 'grid').all() -- cgit v1.2.3 From 6bbd3c0c62d02ac5641ba77a33f7c5d100320ce0 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Tue, 2 Nov 2021 14:38:01 +0100 Subject: Precise the torus is flat Co-authored-by: Marc Glisse --- src/python/doc/datasets_generators.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/doc/datasets_generators.rst b/src/python/doc/datasets_generators.rst index 3700b8a2..6f36bce1 100644 --- a/src/python/doc/datasets_generators.rst +++ b/src/python/doc/datasets_generators.rst @@ -41,7 +41,7 @@ Example .. autofunction:: gudhi.datasets.generators.points.sphere -Points on torus +Points on a flat torus ^^^^^^^^^^^^^^^^ You can also generate points on a torus. -- cgit v1.2.3 From 93df8a0622836ab03ada2eac075132388708d2c4 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Tue, 2 Nov 2021 14:38:46 +0100 Subject: Apply MG's suggestion --- src/python/gudhi/datasets/generators/_points.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/gudhi/datasets/generators/_points.cc b/src/python/gudhi/datasets/generators/_points.cc index 5d675930..70ce4925 100644 --- a/src/python/gudhi/datasets/generators/_points.cc +++ b/src/python/gudhi/datasets/generators/_points.cc @@ -36,8 +36,12 @@ py::array_t generate_points_on_sphere(size_t n_samples, int ambient_dim, GUDHI_CHECK(ambient_dim == buf.shape[1], "Py array second dimension not matching the ambient space dimension"); - py::gil_scoped_release release; - auto points_generated = Gudhi::generate_points_on_sphere_d(n_samples, ambient_dim, radius); + std::vector points_generated; + + { + py::gil_scoped_release release; + points_generated = Gudhi::generate_points_on_sphere_d(n_samples, ambient_dim, radius); + } for (size_t i = 0; i < n_samples; i++) for (int j = 0; j < ambient_dim; j++) -- cgit v1.2.3