summaryrefslogtreecommitdiff
path: root/src/python
diff options
context:
space:
mode:
authorHind Montassif <hind.montassif@gmail.com>2021-04-30 11:17:35 +0200
committerHind Montassif <hind.montassif@gmail.com>2021-04-30 11:17:35 +0200
commit1ef113ff6f5db7288e4dc4c18c053b18d90dbf1a (patch)
treedee71e3d0bf0ba4974fc1e6486ca4bd99fb6470a /src/python
parent70387c34b638972b7c51017b81949f32ddd63e39 (diff)
First version of points generation on torus
Diffstat (limited to 'src/python')
-rw-r--r--src/python/CMakeLists.txt4
-rw-r--r--src/python/gudhi/datasets/generators/points/__init__.py0
-rw-r--r--src/python/gudhi/datasets/generators/points/_torus.cc70
-rw-r--r--src/python/gudhi/datasets/generators/points/torus.py52
4 files changed, 126 insertions, 0 deletions
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
--- /dev/null
+++ b/src/python/gudhi/datasets/generators/points/__init__.py
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 <pybind11/pybind11.h>
+#include <pybind11/numpy.h>
+
+#include <gudhi/random_point_generators.h>
+#include <gudhi/Debug_utils.h>
+
+#include <CGAL/Epick_d.h>
+
+namespace py = pybind11;
+
+
+typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern;
+
+
+py::array_t<double> generate_points_on_torus(size_t num_points, int dim, bool uniform) {
+
+ std::vector<typename Kern::Point_d> points_generated;
+
+ {
+ py::gil_scoped_release release;
+ points_generated = Gudhi::generate_points_on_torus_d<Kern>(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<double> points({npoints, (size_t)2*dim});
+
+ py::buffer_info buf = points.request();
+ double *ptr = static_cast<double *>(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