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 ++ 4 files changed, 117 insertions(+) create mode 100644 src/python/doc/datasets_generators.inc create mode 100644 src/python/doc/datasets_generators.rst (limited to 'src/python/doc') 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 -- 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/python/doc') 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/python/doc') 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/python/doc') 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/python/doc') 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/python/doc') 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 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/python/doc') 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 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/python/doc') 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