summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2019-04-18 10:58:55 +0200
committerMarc Glisse <marc.glisse@inria.fr>2019-04-18 10:58:55 +0200
commitc5bc4c3bfed118f0cb2d4903cd1cee4a2a7ba222 (patch)
treeba02ca87aa1504947b39c4108b987c92190df9f6
parent6525c78704489b0c8cb62b2e3f882ce6113c0f0d (diff)
parent145f6084b734c24d594ab7dddf5a664953ca4545 (diff)
Merge remote-tracking branch 'origin/master' into sparsev3
-rw-r--r--.appveyor.yml69
-rw-r--r--.circleci/config.yml91
-rw-r--r--.travis.yml83
-rw-r--r--Dockerfile_ubuntu58
-rw-r--r--README.md2
-rw-r--r--src/Alpha_complex/utilities/CMakeLists.txt8
-rw-r--r--src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp24
-rw-r--r--src/Alpha_complex/utilities/alphacomplex.md1
-rw-r--r--src/Tangential_complex/doc/Intro_tangential_complex.h20
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex.h13
-rw-r--r--src/Tangential_complex/test/test_tangential_complex.cpp30
-rw-r--r--src/cmake/modules/GUDHI_third_party_libraries.cmake23
-rw-r--r--src/cython/cython/tangential_complex.pyx26
-rw-r--r--src/cython/doc/installation.rst56
-rw-r--r--src/cython/doc/tangential_complex_user.rst17
-rwxr-xr-xsrc/cython/example/tangential_complex_plain_homology_from_off_file_example.py1
-rw-r--r--src/cython/include/Tangential_complex_interface.h15
-rwxr-xr-xsrc/cython/test/test_tangential_complex.py9
18 files changed, 447 insertions, 99 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 00000000..86199265
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,69 @@
+# Specify version format
+version: "{build}"
+
+image:
+ - Visual Studio 2017
+
+platform:
+ - x64
+
+# specify custom environment variables
+environment:
+ APPVEYOR_SAVE_CACHE_ON_ERROR: true
+
+# build configuration, i.e. Debug, Release, etc.
+configuration:
+ - Debug
+ - Release
+
+# scripts that are called at very beginning, before repo cloning
+init:
+ - cmd: cmake --version
+ - cmd: msbuild /version
+
+# scripts that run after cloning repository
+install:
+ #------------------
+ # Windows 10
+ #------------------
+ # update vcpkg
+ - cmd: cd C:\tools\vcpkg
+ - cmd: git pull
+ - cmd: .\bootstrap-vcpkg.bat
+
+ - cmd: if "%platform%"=="Win32" set VCPKG_ARCH=x86-windows
+ - cmd: if "%platform%"=="x64" set VCPKG_ARCH=x64-windows
+
+ # remove outdated versions
+ - cmd: vcpkg remove --outdated --recurse
+
+ # install required dependencies
+ - cmd: vcpkg install --recurse --triplet %VCPKG_ARCH% zlib boost-date-time boost-program-options boost-system boost-serialization boost-thread boost-units tbb eigen3 cgal[core]
+
+ - cmd: vcpkg integrate install
+ - cmd: cd "%APPVEYOR_BUILD_FOLDER%"
+
+# preserve contents of selected directories and files across project builds
+for:
+-
+ matrix:
+ only:
+ - image: Visual Studio 2017
+ cache:
+ - 'C:\tools\vcpkg\installed'
+
+build_script:
+ # get VCG library
+ - git clone https://github.com/GUDHI/gudhi-devel.git
+
+ #------------------
+ # Windows 10
+ #------------------
+ - cmd: if "%platform%"=="Win32" set CMAKE_GENERATOR=-G"Visual Studio 15 2017"
+ - cmd: if "%platform%"=="x64" set CMAKE_GENERATOR=-G"Visual Studio 15 2017 Win64"
+ - cmd: mkdir build && cd build
+ - cmd: cmake %CMAKE_GENERATOR% -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_TOOLCHAIN_FILE="C:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCG_ROOT="%APPVEYOR_BUILD_FOLDER%\VCG" ..
+ - cmd: cmake --build . --target ALL_BUILD --config %Configuration% -- /maxcpucount:4
+
+test_script:
+ - cmd: ctest --build-config %Configuration% --output-on-failure
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 00000000..b9f0376e
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,91 @@
+version: 2.0
+jobs:
+ examples:
+ docker:
+ - image: gudhi/ci_for_gudhi:latest
+ steps:
+ - checkout
+ - run:
+ name: Build and test examples
+ command: |
+ mkdir build;
+ cd build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF ..;
+ make all test;
+
+ tests:
+ docker:
+ - image: gudhi/ci_for_gudhi:latest
+ steps:
+ - checkout
+ - run:
+ name: Build and test unitary tests
+ command: |
+ mkdir build;
+ cd build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF ..;
+ make all test;
+
+ utils:
+ docker:
+ - image: gudhi/ci_for_gudhi:latest
+ steps:
+ - checkout
+ - run:
+ name: Build and test utilities
+ command: |
+ mkdir build;
+ cd build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF ..;
+ make all test;
+
+ python:
+ docker:
+ - image: gudhi/ci_for_gudhi:latest
+ steps:
+ - checkout
+ - run:
+ name: Build and test python module. Generates and tests the python documentation
+ command: |
+ mkdir build;
+ cd build;
+ cmake -DUSER_VERSION_DIR=version ..;
+ make user_version;
+ cd version;
+ mkdir build;
+ cd build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..;
+ make all test sphinx;
+ cp -R cython/sphinx /tmp/sphinx;
+
+ - store_artifacts:
+ path: /tmp/sphinx
+
+ doxygen:
+ docker:
+ - image: gudhi/ci_for_gudhi:latest
+ steps:
+ - checkout
+ - run:
+ name: Generates the C++ documentation with doxygen
+ command: |
+ mkdir build;
+ cd build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF -DUSER_VERSION_DIR=version ..;
+ make doxygen 2>&1 | tee dox.log;
+ grep warning dox.log;
+ cp dox.log version/doc/html/;
+ cp -R version/doc/html /tmp/doxygen;
+
+ - store_artifacts:
+ path: /tmp/doxygen
+
+workflows:
+ version: 2
+ build:
+ jobs:
+ - examples
+ - tests
+ - utils
+ - python
+ - doxygen \ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index b874123c..b8a080ea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,52 +1,68 @@
language: cpp
-dist: xenial
+
sudo: required
+
git:
depth: 3
-env:
- matrix:
-# Only examples and associated tests
- - CMAKE_EXAMPLE='ON' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
-# Only unitary tests
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='ON' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
-# Only utilities and associated tests
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='ON' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
-# Only doxygen documentation
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='doxygen'
-# Only Python, associated tests and sphinx documentation
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='ON' MAKE_TARGET='test sphinx'
+
+matrix:
+ include:
+ # A. Mac OSX
+ - os: osx
+ osx_image: xcode9.4
+ compiler: clang
+ env:
+ # 1. Only examples and associated tests
+ - CMAKE_EXAMPLE='ON' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
+ - os: osx
+ osx_image: xcode9.4
+ compiler: clang
+ env:
+ # 2. Only unitary tests
+ - CMAKE_EXAMPLE='OFF' CMAKE_TEST='ON' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
+ - os: osx
+ osx_image: xcode9.4
+ compiler: clang
+ env:
+ # 3. Only utilities and associated tests
+ - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='ON' CMAKE_PYTHON='OFF' MAKE_TARGET='test'
+ - os: osx
+ osx_image: xcode9.4
+ compiler: clang
+ env:
+ # 4. Only doxygen documentation
+ - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='doxygen'
+ # Issue with sphinx-build with sphinx 2.0.1
+ # - os: osx
+ # osx_image: xcode9.4
+ # compiler: clang
+ # env:
+ # # 5. Only Python, associated tests and sphinx documentation
+ # - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='ON' MAKE_TARGET='test sphinx'
+
cache:
directories:
- $HOME/.cache/pip
-compiler: gcc
+
addons:
- apt:
+ homebrew:
packages:
- cmake
- graphviz
- doxygen
- - libboost-all-dev
- - libeigen3-dev
- - libgmp3-dev
- - libmpfr-dev
- - libtbb-dev
- - curl
+ - boost
+ - eigen
+ - gmp
+ - mpfr
+ - tbb
+ - cgal
- python3
- - python3-pip
- - python3-pytest
- - python3-setuptools
# When installing through libcgal-dev apt, CMake Error at CGAL Exports.cmake The imported target "CGAL::CGAL Qt5" references the file
install:
- - curl -LO "https://github.com/CGAL/cgal/releases/download/releases%2FCGAL-4.13/CGAL-4.13.tar.xz"
- - tar xf CGAL-4.13.tar.xz
- - cd CGAL-4.13
- - cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_HEADER_ONLY=ON .
- - make all
- - sudo make install
- - cd ..
- - pip3 install --upgrade pip
- - pip3 install --user Cython sphinx sphinxcontrib-bibtex matplotlib numpy scipy
+ - python3 -m pip install --upgrade pip setuptools wheel
+ - python3 -m pip install --user pytest Cython sphinx sphinxcontrib-bibtex matplotlib numpy scipy
+
script:
- rm -rf build
- mkdir -p build
@@ -54,6 +70,7 @@ script:
- cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=${CMAKE_EXAMPLE} -DWITH_GUDHI_TEST=${CMAKE_TEST} -DWITH_GUDHI_UTILITIES=${CMAKE_UTILITIES} -DWITH_GUDHI_PYTHON=${CMAKE_PYTHON} -DUSER_VERSION_DIR=version -DPython_ADDITIONAL_VERSIONS=3 ..
- make all ${MAKE_TARGET}
- cd ..
+
notifications:
email:
on_success: change # default: always
diff --git a/Dockerfile_ubuntu b/Dockerfile_ubuntu
new file mode 100644
index 00000000..b80dbc54
--- /dev/null
+++ b/Dockerfile_ubuntu
@@ -0,0 +1,58 @@
+FROM ubuntu:latest
+
+# Update and upgrade distribution
+RUN apt-get update && \
+ apt-get upgrade -y
+
+# Tools necessary for installing and configuring Ubuntu
+RUN apt-get install -y \
+ apt-utils \
+ locales \
+ tzdata
+
+# Timezone
+RUN echo "Europe/Paris" | tee /etc/timezone && \
+ ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime && \
+ dpkg-reconfigure -f noninteractive tzdata
+
+# Locale with UTF-8 support
+RUN echo en_US.UTF-8 UTF-8 >> /etc/locale.gen && \
+ locale-gen && \
+ update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_ALL en_US.UTF-8
+
+# Required for Gudhi compilation
+RUN apt-get install -y make \
+ g++ \
+ cmake \
+ graphviz \
+ perl \
+ texlive-bibtex-extra \
+ biber \
+ doxygen \
+ libboost-all-dev \
+ libeigen3-dev \
+ libgmp3-dev \
+ libmpfr-dev \
+ libtbb-dev \
+ libcgal-dev \
+ locales \
+ python3 \
+ python3-pip \
+ python3-pytest \
+ python3-tk \
+ libfreetype6-dev \
+ pkg-config
+
+RUN pip3 install \
+ numpy \
+ matplotlib \
+ scipy \
+ Cython \
+ sphinx \
+ sphinxcontrib-bibtex
+
+# apt clean up
+RUN apt autoremove && rm -rf /var/lib/apt/lists/*
diff --git a/README.md b/README.md
index f8aadd9d..6cc05ff6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
[![Build Status](https://travis-ci.org/GUDHI/gudhi-devel.svg?branch=master)](https://travis-ci.org/GUDHI/gudhi-devel)
+[![CircleCI](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master.svg?style=svg)](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master)
+
![GUDHI](src/common/doc/Gudhi_banner.png "Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding")
The GUDHI library is a generic open source C++ library, with a Python interface, for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding. The library offers state-of-the-art data structures and algorithms to construct simplicial complexes and compute persistent homology.
diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt
index b12c9690..e76edc5f 100644
--- a/src/Alpha_complex/utilities/CMakeLists.txt
+++ b/src/Alpha_complex/utilities/CMakeLists.txt
@@ -23,7 +23,7 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
"${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
- "-p" "2" "-m" "0.45" "-o" "alpha.pers")
+ "-p" "2" "-m" "0.45" "-o" "safe.pers")
add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
"${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
@@ -31,13 +31,13 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
add_test(NAME Alpha_complex_utilities_safe_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
"${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
- "-p" "2" "-m" "0.45" "-o" "safe.pers" "-s")
+ "-p" "2" "-m" "0.45" "-o" "fast.pers" "-f")
if (DIFF_PATH)
add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH}
- "exact.pers" "alpha.pers")
+ "exact.pers" "safe.pers")
add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH}
- "safe.pers" "alpha.pers")
+ "fast.pers" "safe.pers")
endif()
add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
diff --git a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
index 19e608ad..09c84eb3 100644
--- a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
+++ b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
@@ -94,11 +94,11 @@ int main(int argc, char **argv) {
int coeff_field_characteristic = 0;
Filtration_value min_persistence = 0.;
bool exact_version = false;
- bool safe_version = false;
+ bool fast_version = false;
bool weighted_version = false;
bool periodic_version = false;
- program_options(argc, argv, off_file_points, exact_version, safe_version, weight_file, cuboid_file, output_file_diag,
+ program_options(argc, argv, off_file_points, exact_version, fast_version, weight_file, cuboid_file, output_file_diag,
alpha_square_max_value, coeff_field_characteristic, min_persistence);
std::vector<double> weights;
@@ -120,16 +120,16 @@ int main(int argc, char **argv) {
periodic_version = true;
}
- Gudhi::alpha_complex::complexity complexity = Gudhi::alpha_complex::complexity::FAST;
+ Gudhi::alpha_complex::complexity complexity = Gudhi::alpha_complex::complexity::SAFE;
if (exact_version) {
- if (safe_version) {
- std::cerr << "You cannot set the exact and the safe version." << std::endl;
+ if (fast_version) {
+ std::cerr << "You cannot set the exact and the fast version." << std::endl;
exit(-1);
}
complexity = Gudhi::alpha_complex::complexity::EXACT;
}
- if (safe_version) {
- complexity = Gudhi::alpha_complex::complexity::SAFE;
+ if (fast_version) {
+ complexity = Gudhi::alpha_complex::complexity::FAST;
}
Simplex_tree simplex_tree;
@@ -258,7 +258,7 @@ int main(int argc, char **argv) {
return 0;
}
-void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &safe,
+void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &fast,
std::string &weight_file, std::string &cuboid_file, std::string &output_file_diag,
Filtration_value &alpha_square_max_value, int &coeff_field_characteristic,
Filtration_value &min_persistence) {
@@ -270,9 +270,9 @@ void program_options(int argc, char *argv[], std::string &off_file_points, bool
po::options_description visible("Allowed options", 100);
visible.add_options()("help,h", "produce help message")(
"exact,e", po::bool_switch(&exact),
- "To activate exact version of Alpha complex 3d (default is false, not available if safe is set)")(
- "safe,s", po::bool_switch(&safe),
- "To activate safe version of Alpha complex 3d (default is false, not available if exact is set)")(
+ "To activate exact version of Alpha complex 3d (default is false, not available if fast is set)")(
+ "fast,f", po::bool_switch(&fast),
+ "To activate fast version of Alpha complex 3d (default is false, not available if exact is set)")(
"weight-file,w", po::value<std::string>(&weight_file)->default_value(std::string()),
"Name of file containing a point weights. Format is one weight per line:\n W1\n ...\n Wn ")(
"cuboid-file,c", po::value<std::string>(&cuboid_file),
@@ -303,7 +303,7 @@ void program_options(int argc, char *argv[], std::string &off_file_points, bool
std::cout << std::endl;
std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
std::cout << "of a 3D Alpha complex defined on a set of input points.\n";
- std::cout << "3D Alpha complex can be exact or safe, weighted and/or periodic\n\n";
+ std::cout << "3D Alpha complex can be safe (by default) exact or fast, weighted and/or periodic\n\n";
std::cout << "The output diagram contains one bar per line, written with the convention: \n";
std::cout << " p dim b d \n";
std::cout << "where dim is the dimension of the homological feature,\n";
diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md
index 98f56802..50a39d32 100644
--- a/src/Alpha_complex/utilities/alphacomplex.md
+++ b/src/Alpha_complex/utilities/alphacomplex.md
@@ -107,6 +107,7 @@ It must be in the format described
points (one value per line).
* `-e [ --exact ]` for the exact computation version (not compatible with
weight and periodic version).
+* `-f [ --fast ]` for the fast computation version.
**Example**
diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h
index f4fc8ac7..501f4a8b 100644
--- a/src/Tangential_complex/doc/Intro_tangential_complex.h
+++ b/src/Tangential_complex/doc/Intro_tangential_complex.h
@@ -35,9 +35,11 @@ namespace tangential_complex {
\section tangentialdefinition Definition
-A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+A Tangential Delaunay complex is a
+<a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
designed to reconstruct a \f$k\f$-dimensional smooth manifold embedded in \f$d\f$-dimensional Euclidean space.
-The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of "small" intrinsic dimension.
+The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of
+"small" intrinsic dimension.
The running time depends only linearly on the extrinsic dimension \f$ d \f$
and exponentially on the intrinsic dimension \f$ k \f$.
@@ -46,17 +48,19 @@ An extensive description of the Tangential complex can be found in \cite tangent
\subsection whatisthetc What is a Tangential Complex?
Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$.
-The input data is 4 points \f$ P \f$ located on a curve embedded in 2D.
+The point set \f$ \mathscr P \f$ is located on a closed curve embedded in 2D.
+Only 4 points will be displayed (more are required for PCA) to simplify the figures.
\image html "tc_example_01.png" "The input"
-For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ (e.g. using PCA).
+For each point \f$ P \f$, estimate its tangent subspace \f$ T_P \f$ using PCA.
\image html "tc_example_02.png" "The estimated normals"
-Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$.
+Let us add the Voronoi diagram of the points in orange. For each point \f$ P \f$, construct its star in the Delaunay
+triangulation of \f$ \mathscr P \f$ restricted to \f$ T_P \f$.
\image html "tc_example_03.png" "The Voronoi diagram"
The Tangential Delaunay complex is the union of those stars.
In practice, neither the ambient Voronoi diagram nor the ambient Delaunay triangulation is computed.
-Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only need the star of each point.
-More details can be found in \cite tangentialcomplex2014.
+Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only
+need the star of each point. More details can be found in \cite tangentialcomplex2014.
\subsection inconsistencies Inconsistencies
@@ -65,7 +69,7 @@ An inconsistency occurs when a simplex is not in the star of all its vertices.
Let us take the same example.
\image html "tc_example_07_before.png" "Before"
-Let us slightly move the tangent subspace \f$ T_q \f$
+Let us slightly move the tangent subspace \f$ T_Q \f$
\image html "tc_example_07_after.png" "After"
Now, the star of \f$ Q \f$ contains \f$ QP \f$, but the star of \f$ P \f$ does not contain \f$ QP \f$. We have an inconsistency.
\image html "tc_example_08.png" "After"
diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h
index 37cdf1b4..4a78127c 100644
--- a/src/Tangential_complex/include/gudhi/Tangential_complex.h
+++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h
@@ -322,7 +322,11 @@ class Tangential_complex {
for (std::size_t i = 0; i < m_points.size(); ++i) m_are_tangent_spaces_computed[i] = true;
}
- /// Computes the tangential complex.
+ /** \brief Computes the tangential complex.
+ * \exception std::invalid_argument In debug mode, if the computed star dimension is too low. Try to set a bigger
+ * maximal edge length value with `Tangential_complex::set_max_squared_edge_length` if
+ * this happens.
+ */
void compute_tangential_complex() {
#ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS
std::cerr << red << "WARNING: GUDHI_TC_PERFORM_EXTRA_CHECKS is defined. "
@@ -1984,6 +1988,13 @@ class Tangential_complex {
return os;
}
+ /** \brief Sets the maximal possible squared edge length for the edges in the triangulations.
+ *
+ * @param[in] max_squared_edge_length Maximal possible squared edge length.
+ *
+ * If the maximal edge length value is too low `Tangential_complex::compute_tangential_complex` will throw an
+ * exception in debug mode.
+ */
void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; }
private:
diff --git a/src/Tangential_complex/test/test_tangential_complex.cpp b/src/Tangential_complex/test/test_tangential_complex.cpp
index 4e2d4f65..103b8b30 100644
--- a/src/Tangential_complex/test/test_tangential_complex.cpp
+++ b/src/Tangential_complex/test/test_tangential_complex.cpp
@@ -126,3 +126,33 @@ BOOST_AUTO_TEST_CASE(test_mini_tangential) {
BOOST_CHECK(stree.num_vertices() == 4);
BOOST_CHECK(stree.num_simplices() == 6);
}
+
+#ifdef GUDHI_DEBUG
+BOOST_AUTO_TEST_CASE(test_basic_example_throw) {
+ typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
+ typedef Kernel::FT FT;
+ typedef Kernel::Point_d Point;
+ typedef Kernel::Vector_d Vector;
+ typedef tc::Tangential_complex<Kernel, CGAL::Dynamic_dimension_tag,CGAL::Parallel_tag> TC;
+
+ const int INTRINSIC_DIM = 2;
+ const int AMBIENT_DIM = 3;
+ const int NUM_POINTS = 1000;
+
+ Kernel k;
+
+ // Generate points on a 2-sphere
+ CGAL::Random_points_on_sphere_d<Point> generator(AMBIENT_DIM, 3.);
+ std::vector<Point> points;
+ points.reserve(NUM_POINTS);
+ for (int i = 0; i < NUM_POINTS; ++i)
+ points.push_back(*generator++);
+
+ // Compute the TC
+ TC tc(points, INTRINSIC_DIM, k);
+ tc.set_max_squared_edge_length(0.01);
+ std::cout << "test_basic_example_throw - set_max_squared_edge_length(0.01) to make GUDHI_CHECK fail" << std::endl;
+ BOOST_CHECK_THROW(tc.compute_tangential_complex(), std::invalid_argument);
+
+}
+#endif
diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake
index 7b0d350d..57ea7d14 100644
--- a/src/cmake/modules/GUDHI_third_party_libraries.cmake
+++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake
@@ -148,6 +148,7 @@ if( PYTHONINTERP_FOUND )
find_python_module("matplotlib")
find_python_module("numpy")
find_python_module("scipy")
+ find_python_module("sphinx")
endif()
if(NOT GUDHI_CYTHON_PATH)
@@ -157,20 +158,16 @@ endif(NOT GUDHI_CYTHON_PATH)
option(WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "Build with setting runtime_library_dirs. Usefull when setting rpath is not allowed" ON)
if(PYTHONINTERP_FOUND AND CYTHON_FOUND)
- # Default found version 2
- if(PYTHON_VERSION_MAJOR EQUAL 2)
+ if(SPHINX_FOUND)
# Documentation generation is available through sphinx
find_program( SPHINX_PATH sphinx-build )
- elseif(PYTHON_VERSION_MAJOR EQUAL 3)
- # No sphinx-build in Pyton3, just hack it
- set(SPHINX_PATH "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/doc/python3-sphinx-build.py")
- else()
- message(FATAL_ERROR "ERROR: Try to compile the Cython interface. Python version ${PYTHON_VERSION_STRING} is not valid.")
- endif(PYTHON_VERSION_MAJOR EQUAL 2)
- # get PYTHON_SITE_PACKAGES relative path from a python command line
- execute_process(
- COMMAND "${PYTHON_EXECUTABLE}" -c "from distutils.sysconfig import get_python_lib; print (get_python_lib(prefix='', plat_specific=True))"
- OUTPUT_VARIABLE PYTHON_SITE_PACKAGES
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if(NOT SPHINX_PATH)
+ if(PYTHON_VERSION_MAJOR EQUAL 3)
+ # In Python3, just hack sphinx-build if it does not exist
+ set(SPHINX_PATH "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/doc/python3-sphinx-build.py")
+ endif(PYTHON_VERSION_MAJOR EQUAL 3)
+ endif(NOT SPHINX_PATH)
+ endif(SPHINX_FOUND)
endif(PYTHONINTERP_FOUND AND CYTHON_FOUND)
diff --git a/src/cython/cython/tangential_complex.pyx b/src/cython/cython/tangential_complex.pyx
index 4bb07076..293ef8cb 100644
--- a/src/cython/cython/tangential_complex.pyx
+++ b/src/cython/cython/tangential_complex.pyx
@@ -36,6 +36,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi":
Tangential_complex_interface(int intrisic_dim, vector[vector[double]] points)
# bool from_file is a workaround for cython to find the correct signature
Tangential_complex_interface(int intrisic_dim, string off_file, bool from_file)
+ void compute_tangential_complex() except +
vector[double] get_point(unsigned vertex)
unsigned number_of_vertices()
unsigned number_of_simplices()
@@ -43,6 +44,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi":
unsigned number_of_inconsistent_stars()
void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree)
void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit)
+ void set_max_squared_edge_length(double max_squared_edge_length)
# TangentialComplex python interface
cdef class TangentialComplex:
@@ -92,6 +94,17 @@ cdef class TangentialComplex:
"""
return self.thisptr != NULL
+ def compute_tangential_complex(self):
+ """This function computes the tangential complex.
+
+ Raises:
+ ValueError: In debug mode, if the computed star dimension is too
+ low. Try to set a bigger maximal edge length value with
+ :func:`~gudhi.Tangential_complex.set_max_squared_edge_length`
+ if this happens.
+ """
+ self.thisptr.compute_tangential_complex()
+
def get_point(self, vertex):
"""This function returns the point corresponding to a given vertex.
@@ -152,3 +165,16 @@ cdef class TangentialComplex:
"""
self.thisptr.fix_inconsistencies_using_perturbation(max_perturb,
time_limit)
+
+ def set_max_squared_edge_length(self, max_squared_edge_length):
+ """Sets the maximal possible squared edge length for the edges in the
+ triangulations.
+
+ :param max_squared_edge_length: Maximal possible squared edge length.
+ :type max_squared_edge_length: double
+
+ If the maximal edge length value is too low
+ :func:`~gudhi.Tangential_complex.compute_tangential_complex`
+ will throw an exception in debug mode.
+ """
+ self.thisptr.set_max_squared_edge_length(max_squared_edge_length)
diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst
index 040f6b4a..855dea44 100644
--- a/src/cython/doc/installation.rst
+++ b/src/cython/doc/installation.rst
@@ -7,24 +7,23 @@ Installation
Compiling
*********
-The library uses c++11 and requires `Boost <https://www.boost.org/>`_ ≥ 1.56.0
-and `CMake <https://www.cmake.org/>`_ ≥ 3.1.
+The library uses c++11 and requires `Boost <https://www.boost.org/>`_ ≥ 1.56.0,
+`CMake <https://www.cmake.org/>`_ ≥ 3.1 to generate makefiles, and
+`Cython <https://www.cython.org/>`_ to compile the GUDHI Python module.
It is a multi-platform library and compiles on Linux, Mac OSX and Visual
Studio 2015.
-It also requires cmake to generate makefiles, and cython to compile the
-library.
On `Windows <https://wiki.python.org/moin/WindowsCompilers>`_ , only Python
3.5 and 3.6 are available because of the required Visual Studio version.
-On other systems, if you have several Python/cython installed, the version 2.X
+On other systems, if you have several Python/Cython installed, the version 2.X
will be used by default, but you can force it by adding
:code:`-DPython_ADDITIONAL_VERSIONS=3` to the cmake command.
-GUDHI Cythonization
-===================
+GUDHI Python module compilation
+===============================
-To build the GUDHI cython module, run the following commands in a terminal:
+To build the GUDHI Python module, run the following commands in a terminal:
.. code-block:: bash
@@ -32,7 +31,28 @@ To build the GUDHI cython module, run the following commands in a terminal:
mkdir build
cd build/
cmake ..
- make cython
+ cd cython
+ make
+
+GUDHI Python module installation
+================================
+
+Once the compilation succeeds, one can add the GUDHI Python module path to the
+PYTHONPATH:
+
+.. code-block:: bash
+
+ # For windows, you have to set PYTHONPATH environment variable
+ export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython'
+
+Or install it definitely in your Python packages folder:
+
+.. code-block:: bash
+
+ cd /path-to-gudhi/build/cython
+ # May require sudo or administrator privileges
+ make install
+
Test suites
===========
@@ -45,7 +65,7 @@ following command in a terminal:
cd /path-to-gudhi/build/cython
# For windows, you have to set PYTHONPATH environment variable
export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython'
- ctest -R py_test
+ make test
Debugging issues
================
@@ -54,7 +74,7 @@ If tests fail, please check your PYTHONPATH and try to :code:`import gudhi`
and check the errors.
The problem can come from a third-party library bad link or installation.
-If :code:`import gudhi` succeeds, please have a look to debug informations:
+If :code:`import gudhi` succeeds, please have a look to debug information:
.. code-block:: python
@@ -105,13 +125,17 @@ A complete configuration would be :
Documentation
=============
-To build the documentation, `sphinx-doc <http://http://www.sphinx-doc.org>`_ is
-required. Please refer to *conf.py* file to see which
-`sphinx-doc <http://http://www.sphinx-doc.org>`_ modules are required to
-generate the documentation. Run the following commands in a terminal:
+To build the documentation, `sphinx-doc <http://www.sphinx-doc.org>`_ and
+`sphinxcontrib-bibtex <https://sphinxcontrib-bibtex.readthedocs.io>`_ are
+required. As the documentation is auto-tested, `CGAL`_, `Eigen3`_,
+`Matplotlib`_, `NumPy`_ and `SciPy`_ are also mandatory to build the
+documentation.
+
+Run the following commands in a terminal:
.. code-block:: bash
+ cd /path-to-gudhi/build/cython
make sphinx
Optional third-party library
@@ -127,7 +151,7 @@ The :doc:`Alpha complex </alpha_complex_user>`,
C++ library which provides easy access to efficient and reliable geometric
algorithms.
-Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or
+Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or
higher installed is recommended. The procedure to install this library
according to your operating system is detailed
`here <http://doc.cgal.org/latest/Manual/installation.html>`_.
diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst
index 5ce69e86..ebfe1e29 100644
--- a/src/cython/doc/tangential_complex_user.rst
+++ b/src/cython/doc/tangential_complex_user.rst
@@ -23,8 +23,10 @@ What is a Tangential Complex?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Let us start with the description of the Tangential complex of a simple
-example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points
-:math:`P` located on a curve embedded in 2D.
+example, with :math:`k = 1` and :math:`d = 2`. The point set
+:math:`\mathscr P` is located on a closed curve embedded in 2D.
+Only 4 points will be displayed (more are required for PCA) to simplify the
+figures.
.. figure:: ../../doc/Tangential_complex/tc_example_01.png
:alt: The input
@@ -32,8 +34,7 @@ example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points
The input
-For each point :math:`p`, estimate its tangent subspace :math:`T_p` (e.g.
-using PCA).
+For each point :math:`P`, estimate its tangent subspace :math:`T_P` using PCA.
.. figure:: ../../doc/Tangential_complex/tc_example_02.png
:alt: The estimated normals
@@ -43,8 +44,8 @@ using PCA).
Let us add the Voronoi diagram of the points in orange. For each point
-:math:`p`, construct its star in the Delaunay triangulation of :math:`P`
-restricted to :math:`T_p`.
+:math:`P`, construct its star in the Delaunay triangulation of
+:math:`\mathscr P` restricted to :math:`T_P`.
.. figure:: ../../doc/Tangential_complex/tc_example_03.png
:alt: The Voronoi diagram
@@ -72,7 +73,7 @@ Let us take the same example.
Before
-Let us slightly move the tangent subspace :math:`T_q`
+Let us slightly move the tangent subspace :math:`T_Q`
.. figure:: ../../doc/Tangential_complex/tc_example_07_after.png
:alt: After
@@ -128,6 +129,7 @@ This example builds the Tangential complex of point set read in an OFF file.
import gudhi
tc = gudhi.TangentialComplex(intrisic_dim = 1,
off_file=gudhi.__root_source_dir__ + '/data/points/alphacomplexdoc.off')
+ tc.compute_tangential_complex()
result_str = 'Tangential contains ' + repr(tc.num_simplices()) + \
' simplices - ' + repr(tc.num_vertices()) + ' vertices.'
print(result_str)
@@ -175,6 +177,7 @@ simplices.
import gudhi
tc = gudhi.TangentialComplex(intrisic_dim = 1,
points=[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]])
+ tc.compute_tangential_complex()
result_str = 'Tangential contains ' + repr(tc.num_vertices()) + ' vertices.'
print(result_str)
diff --git a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py
index 0f8f5e80..536517d1 100755
--- a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py
+++ b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py
@@ -50,6 +50,7 @@ with open(args.file, 'r') as f:
print("TangentialComplex creation from points read in a OFF file")
tc = gudhi.TangentialComplex(intrisic_dim = args.intrisic_dim, off_file=args.file)
+ tc.compute_tangential_complex()
st = tc.create_simplex_tree()
message = "Number of simplices=" + repr(st.num_simplices())
diff --git a/src/cython/include/Tangential_complex_interface.h b/src/cython/include/Tangential_complex_interface.h
index 71418886..c4ddbdbe 100644
--- a/src/cython/include/Tangential_complex_interface.h
+++ b/src/cython/include/Tangential_complex_interface.h
@@ -49,8 +49,6 @@ class Tangential_complex_interface {
Dynamic_kernel k;
tangential_complex_ = new TC(points, intrisic_dim, k);
- tangential_complex_->compute_tangential_complex();
- num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices();
}
Tangential_complex_interface(int intrisic_dim, const std::string& off_file_name, bool from_file = true) {
@@ -60,14 +58,17 @@ class Tangential_complex_interface {
std::vector<Point_d> points = off_reader.get_point_cloud();
tangential_complex_ = new TC(points, intrisic_dim, k);
- tangential_complex_->compute_tangential_complex();
- num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices();
}
~Tangential_complex_interface() {
delete tangential_complex_;
}
+ void compute_tangential_complex() {
+ tangential_complex_->compute_tangential_complex();
+ num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices();
+ }
+
std::vector<double> get_point(unsigned vh) {
std::vector<double> vd;
if (vh < tangential_complex_->number_of_vertices()) {
@@ -104,7 +105,11 @@ class Tangential_complex_interface {
simplex_tree->initialize_filtration();
}
- private:
+ void set_max_squared_edge_length(double max_squared_edge_length) {
+ tangential_complex_->set_max_squared_edge_length(max_squared_edge_length);
+ }
+
+private:
TC* tangential_complex_;
TC::Num_inconsistencies num_inconsistencies_;
};
diff --git a/src/cython/test/test_tangential_complex.py b/src/cython/test/test_tangential_complex.py
index 5385a0d3..5c62f278 100755
--- a/src/cython/test/test_tangential_complex.py
+++ b/src/cython/test/test_tangential_complex.py
@@ -32,6 +32,15 @@ def test_tangential():
tc = TangentialComplex(intrisic_dim = 1, points=point_list)
assert tc.__is_defined() == True
assert tc.num_vertices() == 4
+ assert tc.num_simplices() == 0
+ assert tc.num_inconsistent_simplices() == 0
+ assert tc.num_inconsistent_stars() == 0
+
+ tc.compute_tangential_complex()
+ assert tc.num_vertices() == 4
+ assert tc.num_simplices() == 4
+ assert tc.num_inconsistent_simplices() == 0
+ assert tc.num_inconsistent_stars() == 0
st = tc.create_simplex_tree()
assert st.__is_defined() == True