diff options
Diffstat (limited to 'src')
34 files changed, 475 insertions, 81 deletions
diff --git a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp index 238d99ad..1408681a 100644 --- a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp +++ b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp @@ -36,8 +36,8 @@ int main(int argc, char** argv) { " distance (set by default to zero). The program will now terminate \n"; return -1; } - std::vector<std::pair<double, double>> diag1 = read_persistence_intervals_in_dimension(argv[1]); - std::vector<std::pair<double, double>> diag2 = read_persistence_intervals_in_dimension(argv[2]); + std::vector<std::pair<double, double>> diag1 = Gudhi::read_persistence_intervals_in_dimension(argv[1]); + std::vector<std::pair<double, double>> diag2 = Gudhi::read_persistence_intervals_in_dimension(argv[2]); double tolerance = 0.; if (argc == 4) { diff --git a/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp b/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp index 8517e7f6..d38808c7 100644 --- a/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp +++ b/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp @@ -57,7 +57,7 @@ int main(int argc, char * argv[]) { program_options(argc, argv, csv_matrix_file, filediag, threshold, dim_max, p, min_persistence); - Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_matrix_file); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_matrix_file); Rips_complex rips_complex_from_file(distances, threshold); // Construct the Rips complex in a Simplex Tree diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 672fda48..e0a147b3 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -591,10 +591,17 @@ class Persistent_cohomology { std::ofstream diagram_out(diagram_name.c_str()); cmp_intervals_by_length cmp(cpx_); std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp); + bool has_infinity = std::numeric_limits<Filtration_value>::has_infinity; for (auto pair : persistent_pairs_) { - diagram_out << cpx_->dimension(get<0>(pair)) << " " - << cpx_->filtration(get<0>(pair)) << " " - << cpx_->filtration(get<1>(pair)) << std::endl; + // Special case on windows, inf is "1.#INF" + if (has_infinity && cpx_->filtration(get<1>(pair)) == std::numeric_limits<Filtration_value>::infinity()) { + diagram_out << cpx_->dimension(get<0>(pair)) << " " + << cpx_->filtration(get<0>(pair)) << " inf" << std::endl; + } else { + diagram_out << cpx_->dimension(get<0>(pair)) << " " + << cpx_->filtration(get<0>(pair)) << " " + << cpx_->filtration(get<1>(pair)) << std::endl; + } } } diff --git a/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp index 7ae8126f..9e182f1e 100644 --- a/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp +++ b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp @@ -32,7 +32,7 @@ int main(int argc, char **argv) { // Init of a Rips complex from a distance matrix in a csv file // Default separator is ';' // ---------------------------------------------------------------------------- - Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name); Rips_complex rips_complex_from_file(distances, threshold); std::streambuf* streambufffer; diff --git a/src/Rips_complex/test/test_rips_complex.cpp b/src/Rips_complex/test/test_rips_complex.cpp index fc2179f2..fc83f5f7 100644 --- a/src/Rips_complex/test/test_rips_complex.cpp +++ b/src/Rips_complex/test/test_rips_complex.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(Rips_doc_csv_file) { std::cout << "========== CSV FILE NAME = " << csv_file_name << " - Rips threshold=" << rips_threshold << "==========" << std::endl; - Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name); Rips_complex rips_complex_from_file(distances, rips_threshold); const int DIMENSION_1 = 1; diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 8f486118..dbf2106a 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -117,15 +117,13 @@ if(NOT GUDHI_CYTHON_PATH) endif(NOT GUDHI_CYTHON_PATH) if(PYTHONINTERP_FOUND AND CYTHON_FOUND) - # Unitary tests are available through py.test - find_program( PYTEST_PATH py.test ) # Default found version 2 if(PYTHON_VERSION_MAJOR EQUAL 2) # 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 "${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/doc/python3-sphinx-build") + set(SPHINX_PATH "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_CYTHON_PATH}/doc/python3-sphinx-build") 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) diff --git a/src/common/doc/file_formats.h b/src/common/doc/file_formats.h index 9d0415b1..d715aa4d 100644 --- a/src/common/doc/file_formats.h +++ b/src/common/doc/file_formats.h @@ -26,7 +26,7 @@ namespace Gudhi { /*! \page fileformats File formats - + \tableofcontents \section FileFormatsPers Persistence Diagram @@ -49,6 +49,10 @@ namespace Gudhi { \endverbatim Other sample files can be found in the `data/persistence_diagram` folder. + + Such files can be generated with `Gudhi::persistent_cohomology::Persistent_cohomology::output_diagram()` and read with + `Gudhi::read_persistence_intervals_and_dimension()`, `Gudhi::read_persistence_intervals_grouped_by_dimension()` or + `Gudhi::read_persistence_intervals_in_dimension()`. */ } // namespace Gudhi diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index bda93f4f..90be4fc7 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -38,6 +38,8 @@ #include <utility> // for pair #include <tuple> // for std::make_tuple +namespace Gudhi { + // Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented. // It is required for global functions and variables. @@ -362,4 +364,6 @@ inline std::vector<std::pair<double, double>> read_persistence_intervals_in_dime return ret; } +} // namespace Gudhi + #endif // READER_UTILS_H_ diff --git a/src/common/test/test_distance_matrix_reader.cpp b/src/common/test/test_distance_matrix_reader.cpp index 95a73bd9..656e6f2e 100644 --- a/src/common/test/test_distance_matrix_reader.cpp +++ b/src/common/test/test_distance_matrix_reader.cpp @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( lower_triangular_distance_matrix ) { Distance_matrix from_lower_triangular; // Read lower_triangular_distance_matrix.csv file where the separator is a ',' - from_lower_triangular = read_lower_triangular_matrix_from_csv_file<double>("lower_triangular_distance_matrix.csv", + from_lower_triangular = Gudhi::read_lower_triangular_matrix_from_csv_file<double>("lower_triangular_distance_matrix.csv", ','); for (auto& i : from_lower_triangular) { for (auto j : i) { @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE( full_square_distance_matrix ) { Distance_matrix from_full_square; // Read full_square_distance_matrix.csv file where the separator is the default one ';' - from_full_square = read_lower_triangular_matrix_from_csv_file<double>("full_square_distance_matrix.csv"); + from_full_square = Gudhi::read_lower_triangular_matrix_from_csv_file<double>("full_square_distance_matrix.csv"); for (auto& i : from_full_square) { for (auto j : i) { std::cout << j << " "; diff --git a/src/common/test/test_persistence_intervals_reader.cpp b/src/common/test/test_persistence_intervals_reader.cpp index a06fff1e..be299376 100644 --- a/src/common/test/test_persistence_intervals_reader.cpp +++ b/src/common/test/test_persistence_intervals_reader.cpp @@ -27,6 +27,7 @@ #include <utility> // for pair #include <tuple> #include <limits> // for inf +#include <map> #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE "persistence_intervals_reader" @@ -44,7 +45,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_without_dimension ) expected_intervals_by_dimension[-1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals_by_dimension persistence_intervals_by_dimension = - read_persistence_intervals_grouped_by_dimension("persistence_intervals_without_dimension.pers"); + Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_without_dimension.pers"); std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n"; for (auto map_iter : expected_intervals_by_dimension) { @@ -69,7 +70,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_without_dimension ) expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers"); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers"); std::cout << "\nread_persistence_intervals_in_dimension - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -83,22 +84,22 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_without_dimension ) expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 0); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 0); BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 1); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 1); BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 2); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 2); BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 3); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 3); BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); } @@ -112,7 +113,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals_by_dimension persistence_intervals_by_dimension = - read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_dimension.pers"); + Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_dimension.pers"); std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n"; for (auto map_iter : expected_intervals_by_dimension) { @@ -137,7 +138,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers"); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers"); std::cout << "\nread_persistence_intervals_in_dimension - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -152,7 +153,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_in_dimension.clear(); expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7)); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 0); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 0); std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -168,7 +169,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.)); expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 1); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 1); std::cout << "\nread_persistence_intervals_in_dimension 1 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -182,7 +183,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 2); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 2); std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -197,7 +198,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) expected_intervals_in_dimension.clear(); expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974)); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 3); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 3); std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -221,7 +222,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals_by_dimension persistence_intervals_by_dimension = - read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_field.pers"); + Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_field.pers"); std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n"; for (auto map_iter : expected_intervals_by_dimension) { @@ -246,7 +247,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); Persistence_intervals persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers"); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers"); std::cout << "\nread_persistence_intervals_in_dimension - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -261,7 +262,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_in_dimension.clear(); expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7)); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 0); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 0); std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -277,7 +278,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.)); expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity())); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 1); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 1); std::cout << "\nread_persistence_intervals_in_dimension 1 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -291,7 +292,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_in_dimension.clear(); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 2); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 2); std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) @@ -306,7 +307,7 @@ BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) expected_intervals_in_dimension.clear(); expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974)); persistence_intervals_in_dimension = - read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 3); + Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 3); std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n"; for (auto vec_iter : expected_intervals_in_dimension) diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 99badffb..ab5ea9ef 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -16,7 +16,7 @@ function( add_gudhi_cython_lib THE_LIB ) endfunction( add_gudhi_cython_lib ) if(CYTHON_FOUND) - message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_EXECUTABLE} - py.test is ${PYTEST_PATH} - Sphinx is ${SPHINX_PATH}") + message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_EXECUTABLE} - Sphinx is ${SPHINX_PATH}") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") @@ -100,7 +100,7 @@ if(CYTHON_FOUND) file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") # Persistence graphical tools examples file(COPY "${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") - file(COPY "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") if (NOT CGAL_VERSION VERSION_LESS 4.8.1) # If CGAL_VERSION >= 4.8.1, include subsampling @@ -194,6 +194,7 @@ if(CYTHON_FOUND) endif(UNIX) # set sphinx-build in make files + configure_file(doc/python3-sphinx-build.in "${CMAKE_CURRENT_BINARY_DIR}/doc/python3-sphinx-build" @ONLY) configure_file(doc/Makefile.in "${CMAKE_CURRENT_BINARY_DIR}/doc/Makefile" @ONLY) configure_file(doc/make.bat.in "${CMAKE_CURRENT_BINARY_DIR}/doc/make.bat" @ONLY) @@ -305,13 +306,11 @@ if(CYTHON_FOUND) set_tests_properties(witness_complex_from_nearest_landmark_table_py_test PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}") # Unitary tests are available through py.test - if(PYTEST_PATH) - add_test( - NAME gudhi_cython_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} "${PYTEST_PATH}") - set_tests_properties(gudhi_cython_py_test PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}") - endif(PYTEST_PATH) + add_test( + NAME gudhi_cython_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PYTHON_EXECUTABLE} -m pytest) + set_tests_properties(gudhi_cython_py_test PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}") # Documentation generation is available through sphinx if(SPHINX_PATH) diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index a984633e..fb837e29 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -1,11 +1,12 @@ import matplotlib.pyplot as plt import numpy as np +import os """This file is part of the Gudhi Library. The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic C++ library for computational topology. - Author(s): Vincent Rouvreau + Author(s): Vincent Rouvreau, Bertrand Michel Copyright (C) 2016 INRIA @@ -23,15 +24,17 @@ import numpy as np along with this program. If not, see <http://www.gnu.org/licenses/>. """ -__author__ = "Vincent Rouvreau" +__author__ = "Vincent Rouvreau, Bertrand Michel" __copyright__ = "Copyright (C) 2016 INRIA" __license__ = "GPL v3" -def __min_birth_max_death(persistence): +def __min_birth_max_death(persistence, band_boot=0.): """This function returns (min_birth, max_death) from the persistence. :param persistence: The persistence to plot. :type persistence: list of tuples(dimension, tuple(birth, death)). + :param band_boot: bootstrap band + :type band_boot: float. :returns: (float, float) -- (min_birth, max_death). """ # Look for minimum birth date and maximum death date for plot optimisation @@ -45,6 +48,8 @@ def __min_birth_max_death(persistence): max_death = float(interval[1][0]) if float(interval[1][0]) < min_birth: min_birth = float(interval[1][0]) + if band_boot > 0.: + max_death += band_boot return (min_birth, max_death) """ @@ -59,7 +64,7 @@ def show_palette_values(alpha=0.6): :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). :type alpha: float. - :returns: plot -- An horizontal bar plot of dimensions color. + :returns: plot the dimension palette values. """ colors = [] for color in palette: @@ -70,18 +75,38 @@ def show_palette_values(alpha=0.6): plt.barh(y_pos, y_pos + 1, align='center', alpha=alpha, color=colors) plt.ylabel('Dimension') plt.title('Dimension palette values') + return plt - plt.show() - -def plot_persistence_barcode(persistence, alpha=0.6): +def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6, max_barcodes=0): """This function plots the persistence bar code. :param persistence: The persistence to plot. :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A persistence file style name (reset persistence if both are set). + :type persistence_file: string :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). :type alpha: float. + :param max_barcodes: number of maximal barcodes to be displayed + (persistence will be sorted by life time if max_barcodes is set) + :type max_barcodes: int. :returns: plot -- An horizontal bar plot of persistence. """ + if persistence_file is not '': + if os.path.isfile(persistence_file): + # Reset persistence + persistence = [] + diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) + for key in diag.keys(): + for persistence_interval in diag[key]: + persistence.append((key, persistence_interval)) + else: + print("file " + persistence_file + " not found.") + return None + + if max_barcodes > 0 and max_barcodes < len(persistence): + # Sort by life time, then takes only the max_plots elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_barcodes] + (min_birth, max_death) = __min_birth_max_death(persistence) ind = 0 delta = ((max_death - min_birth) / 10.0) @@ -106,18 +131,40 @@ def plot_persistence_barcode(persistence, alpha=0.6): plt.title('Persistence barcode') # Ends plot on infinity value and starts a little bit before min_birth plt.axis([axis_start, infinity, 0, ind]) - plt.show() + return plt -def plot_persistence_diagram(persistence, alpha=0.6): - """This function plots the persistence diagram. +def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6, band_boot=0., max_plots=0): + """This function plots the persistence diagram with an optional confidence band. :param persistence: The persistence to plot. :type persistence: list of tuples(dimension, tuple(birth, death)). + :param persistence_file: A persistence file style name (reset persistence if both are set). + :type persistence_file: string :param alpha: alpha value in [0.0, 1.0] for points and horizontal infinity line (default is 0.6). :type alpha: float. - :returns: plot -- An diagram plot of persistence. + :param band_boot: bootstrap band (not displayed if :math:`\leq` 0.) + :type band_boot: float. + :param max_plots: number of maximal plots to be displayed + :type max_plots: int. + :returns: plot -- A diagram plot of persistence. """ - (min_birth, max_death) = __min_birth_max_death(persistence) + if persistence_file is not '': + if os.path.isfile(persistence_file): + # Reset persistence + persistence = [] + diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file) + for key in diag.keys(): + for persistence_interval in diag[key]: + persistence.append((key, persistence_interval)) + else: + print("file " + persistence_file + " not found.") + return None + + if max_plots > 0 and max_plots < len(persistence): + # Sort by life time, then takes only the max_plots elements + persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots] + + (min_birth, max_death) = __min_birth_max_death(persistence, band_boot) ind = 0 delta = ((max_death - min_birth) / 10.0) # Replace infinity values with max_death + delta for diagram to be more @@ -131,6 +178,9 @@ def plot_persistence_diagram(persistence, alpha=0.6): plt.plot(x, x, color='k', linewidth=1.0) plt.plot(x, [infinity] * len(x), linewidth=1.0, color='k', alpha=alpha) plt.text(axis_start, infinity, r'$\infty$', color='k', alpha=alpha) + # bootstrap band + if band_boot > 0.: + plt.fill_between(x, x, x+band_boot, alpha=alpha, facecolor='red') # Draw points in loop for interval in reversed(persistence): @@ -149,4 +199,4 @@ def plot_persistence_diagram(persistence, alpha=0.6): plt.ylabel('Death') # Ends plot on infinity value and starts a little bit before min_birth plt.axis([axis_start, infinity, axis_start, infinity + delta]) - plt.show() + return plt diff --git a/src/cython/cython/reader_utils.pyx b/src/cython/cython/reader_utils.pyx new file mode 100644 index 00000000..3a17c5a0 --- /dev/null +++ b/src/cython/cython/reader_utils.pyx @@ -0,0 +1,95 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp.map cimport map +from libcpp.pair cimport pair +import os + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Vincent Rouvreau + + Copyright (C) 2017 INRIA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2017 INRIA" +__license__ = "GPL v3" + +cdef extern from "Reader_utils_interface.h" namespace "Gudhi": + vector[vector[double]] read_matrix_from_csv_file(string off_file, char separator) + map[int, vector[pair[double, double]]] read_pers_intervals_grouped_by_dimension(string filename) + vector[pair[double, double]] read_pers_intervals_in_dimension(string filename, int only_this_dim) + +def read_lower_triangular_matrix_from_csv_file(csv_file='', separator=';'): + """Read lower triangular matrix from a CSV style file. + + :param csv_file: A CSV file style name. + :type csv_file: string + :param separator: The value separator in the CSV file. Default value is ';' + :type separator: char + + :returns: The lower triangular matrix. + :rtype: vector[vector[double]] + """ + if csv_file is not '': + if os.path.isfile(csv_file): + return read_matrix_from_csv_file(str.encode(csv_file), ord(separator[0])) + print("file " + csv_file + " not set or not found.") + return [] + +def read_persistence_intervals_grouped_by_dimension(persistence_file=''): + """Reads a file containing persistence intervals. + Each line might contain 2, 3 or 4 values: [[field] dimension] birth death + The return value is an `map[dim, vector[pair[birth, death]]]` + where `dim` is an `int`, `birth` a `double`, and `death` a `double`. + Note: the function does not check that birth <= death. + + :param persistence_file: A persistence file style name. + :type persistence_file: string + + :returns: The persistence pairs grouped by dimension. + :rtype: map[int, vector[pair[double, double]]] + """ + if persistence_file is not '': + if os.path.isfile(persistence_file): + return read_pers_intervals_grouped_by_dimension(str.encode(persistence_file)) + print("file " + persistence_file + " not set or not found.") + return [] + +def read_persistence_intervals_in_dimension(persistence_file='', only_this_dim=-1): + """Reads a file containing persistence intervals. + Each line might contain 2, 3 or 4 values: [[field] dimension] birth death + If `only_this_dim` = -1, dimension is ignored and all lines are returned. + If `only_this_dim` is >= 0, only the lines where dimension = `only_this_dim` + (or where dimension is not specified) are returned. + The return value is an `vector[pair[birth, death]]` + where `birth` a `double`, and `death` a `double`. + Note: the function does not check that birth <= death. + + :param persistence_file: A persistence file style name. + :type persistence_file: string + + :returns: The persistence pairs grouped by dimension. + :rtype: map[int, vector[pair[double, double]]] + """ + if persistence_file is not '': + if os.path.isfile(persistence_file): + return read_pers_intervals_in_dimension(str.encode(persistence_file), only_this_dim) + print("file " + persistence_file + " not set or not found.") + return [] diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx index 2acdac3c..9e3b2345 100644 --- a/src/cython/cython/simplex_tree.pyx +++ b/src/cython/cython/simplex_tree.pyx @@ -61,6 +61,7 @@ cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": vector[int] betti_numbers() vector[int] persistent_betti_numbers(double from_value, double to_value) vector[pair[double,double]] intervals_in_dimension(int dimension) + void write_output_diagram(string diagram_file_name) # SimplexTree python interface cdef class SimplexTree: @@ -385,7 +386,7 @@ cdef class SimplexTree: complex in a specific dimension. :param dimension: The specific dimension. - :type from_value: int. + :type dimension: int. :returns: The persistence intervals. :rtype: list of pair of float @@ -399,3 +400,22 @@ cdef class SimplexTree: print("intervals_in_dim function requires persistence function" " to be launched first.") return intervals_result + + def write_persistence_diagram(self, persistence_file=''): + """This function writes the persistence intervals of the simplicial + complex in a user given file name. + + :param persistence_file: The specific dimension. + :type persistence_file: string. + + :note: intervals_in_dim function requires persistence function to be + launched first. + """ + if self.pcohptr != NULL: + if persistence_file != '': + self.pcohptr.write_output_diagram(str.encode(persistence_file)) + else: + print("persistence_file must be specified") + else: + print("intervals_in_dim function requires persistence function" + " to be launched first.") diff --git a/src/cython/doc/_templates/layout.html b/src/cython/doc/_templates/layout.html index b11c1236..243f33c6 100644 --- a/src/cython/doc/_templates/layout.html +++ b/src/cython/doc/_templates/layout.html @@ -65,6 +65,7 @@ {#- old style sidebars: using blocks -- should be deprecated #} {%- block sidebartoc %} <h2><a href="index.html">GUDHI</a></h2> +<h2><a href="fileformats.html">File formats</a></h2> <h2><a href="installation.html">GUDHI installation</a></h2> <h2><a href="citation.html">Acknowledging the GUDHI library</a></h2> <h2><a href="genindex.html">Index</a></h2> diff --git a/src/cython/doc/fileformats.rst b/src/cython/doc/fileformats.rst new file mode 100644 index 00000000..156ef4e4 --- /dev/null +++ b/src/cython/doc/fileformats.rst @@ -0,0 +1,33 @@ +File formats +############ + +Persistence Diagram +******************* + +Such a file, whose extension is usually ``.pers``, contains a list of +persistence intervals. + +Lines starting with ``#`` are ignored (comments). + +Other lines might contain 2, 3 or 4 values (the number of values on each line +must be the same for all lines):: + + [[field] dimension] birth death + +Here is a simple sample file:: + + # Persistence diagram example + 2 2.7 3.7 + 2 9.6 14. + # Some comments + 3 34.2 34.974 + 4 3. inf + +Other sample files can be found in the data/persistence_diagram folder. + +Such files can be generated with +:meth:`gudhi.SimplexTree.write_persistence_diagram`, read with +:meth:`gudhi.read_persistence_intervals_grouped_by_dimension`, or +:meth:`gudhi.read_persistence_intervals_in_dimension` and displayed with +:meth:`gudhi.plot_persistence_barcode` or +:meth:`gudhi.plot_persistence_diagram`. diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index cae18323..13198162 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -14,12 +14,14 @@ This function is useful to show the color palette values of dimension: .. testcode:: import gudhi - gudhi.show_palette_values(alpha=1.0) + plt = gudhi.show_palette_values(alpha=1.0) + plt.show() .. plot:: import gudhi - gudhi.show_palette_values(alpha=1.0) + plt = gudhi.show_palette_values(alpha=1.0) + plt.show() Show persistence as a barcode ----------------------------- @@ -32,7 +34,8 @@ This function can display the persistence result as a barcode: periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') diag = periodic_cc.persistence() - gudhi.plot_persistence_barcode(diag) + plt = gudhi.plot_persistence_barcode(diag) + plt.show() .. plot:: @@ -40,7 +43,8 @@ This function can display the persistence result as a barcode: periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') diag = periodic_cc.persistence() - gudhi.plot_persistence_barcode(diag) + plt = gudhi.plot_persistence_barcode(diag) + plt.show() Show persistence as a diagram ----------------------------- @@ -51,16 +55,18 @@ This function can display the persistence result as a diagram: import gudhi - rips_complex = gudhi.RipsComplex(off_file='tore3D_300.off', max_edge_length=2.0) + rips_complex = gudhi.RipsComplex(off_file='tore3D_1307.off', max_edge_length=0.2) simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) diag = simplex_tree.persistence() - gudhi.plot_persistence_diagram(diag) + plt = gudhi.plot_persistence_diagram(diag, band_boot=0.13) + plt.show() .. plot:: import gudhi - rips_complex = gudhi.RipsComplex(off_file='tore3D_300.off', max_edge_length=2.0) + rips_complex = gudhi.RipsComplex(off_file='tore3D_1307.off', max_edge_length=0.2) simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) diag = simplex_tree.persistence() - gudhi.plot_persistence_diagram(diag) + plt = gudhi.plot_persistence_diagram(diag, band_boot=0.13) + plt.show() diff --git a/src/cython/doc/pyplots/barcode_persistence.py b/src/cython/doc/pyplots/barcode_persistence.py index c06ac5a7..9cd3149d 100755 --- a/src/cython/doc/pyplots/barcode_persistence.py +++ b/src/cython/doc/pyplots/barcode_persistence.py @@ -1,5 +1,6 @@ import gudhi -periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='../3d_torus.txt') +periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') diag = periodic_cc.persistence() -gudhi.plot_persistence_barcode(diag) +plt = gudhi.plot_persistence_barcode(diag) +plt.show() diff --git a/src/cython/doc/pyplots/diagram_persistence.py b/src/cython/doc/pyplots/diagram_persistence.py index b4714fe3..30661965 100755 --- a/src/cython/doc/pyplots/diagram_persistence.py +++ b/src/cython/doc/pyplots/diagram_persistence.py @@ -1,5 +1,7 @@ import gudhi -alpha_complex = gudhi.AlphaComplex(off_file='../tore3D_300.off') -diag = alpha_complex.persistence() -gudhi.plot_persistence_diagram(diag) +rips_complex = gudhi.RipsComplex(off_file='tore3D_1307.off', max_edge_length=0.2) +simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) +diag = simplex_tree.persistence() +plt = gudhi.plot_persistence_diagram(diag, band_boot=0.13) +plt.show() diff --git a/src/cython/doc/pyplots/show_palette_values.py b/src/cython/doc/pyplots/show_palette_values.py index e72a55fd..fdf9645f 100755 --- a/src/cython/doc/pyplots/show_palette_values.py +++ b/src/cython/doc/pyplots/show_palette_values.py @@ -1,2 +1,3 @@ import gudhi -gudhi.show_palette_values(alpha=1.0) +plt = gudhi.show_palette_values(alpha=1.0) +plt.show() diff --git a/src/cython/doc/python3-sphinx-build b/src/cython/doc/python3-sphinx-build.in index 44b94169..c97965f5 100755 --- a/src/cython/doc/python3-sphinx-build +++ b/src/cython/doc/python3-sphinx-build.in @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!@PYTHON_EXECUTABLE@ """ Emulate sphinx-build for python3 diff --git a/src/cython/doc/reader_utils_ref.rst b/src/cython/doc/reader_utils_ref.rst new file mode 100644 index 00000000..9c1ea6fc --- /dev/null +++ b/src/cython/doc/reader_utils_ref.rst @@ -0,0 +1,11 @@ +============================= +Reader utils reference manual +============================= + +.. autofunction:: gudhi.read_off + +.. autofunction:: gudhi.read_lower_triangular_matrix_from_csv_file + +.. autofunction:: gudhi.read_persistence_intervals_grouped_by_dimension + +.. autofunction:: gudhi.read_persistence_intervals_in_dimension diff --git a/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py index adedc7d2..b4487be4 100755 --- a/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py +++ b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -38,6 +38,7 @@ parser = argparse.ArgumentParser(description='AlphaComplex creation from ' 'points from the given OFF file.') parser.add_argument("-f", "--file", type=str, required=True) parser.add_argument("-a", "--max_alpha_square", type=float, default=0.5) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -63,7 +64,8 @@ with open(args.file, 'r') as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() else: print(args.file, "is not a valid OFF file") diff --git a/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py index 2371c36c..e3f362dc 100755 --- a/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py +++ b/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py @@ -40,6 +40,7 @@ parser.add_argument("-f", "--file", type=str, required=True) parser.add_argument("-a", "--max_alpha_square", type=float, required=True) parser.add_argument("-n", "--number_of_landmarks", type=int, required=True) parser.add_argument("-d", "--limit_dimension", type=int, required=True) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -70,8 +71,8 @@ with open(args.file, 'r') as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) - + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() else: print(args.file, "is not a valid OFF file") diff --git a/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py index 5748aa8a..c236d992 100755 --- a/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py +++ b/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py @@ -40,6 +40,7 @@ parser.add_argument("-f", "--file", type=str, required=True) parser.add_argument("-a", "--max_alpha_square", type=float, required=True) parser.add_argument("-n", "--number_of_landmarks", type=int, required=True) parser.add_argument("-d", "--limit_dimension", type=int, required=True) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -70,8 +71,8 @@ with open(args.file, 'r') as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) - + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() else: print(args.file, "is not a valid OFF file") diff --git a/src/cython/example/gudhi_graphical_tools_example.py b/src/cython/example/gudhi_graphical_tools_example.py index bc3b16ec..ed87806b 100755 --- a/src/cython/example/gudhi_graphical_tools_example.py +++ b/src/cython/example/gudhi_graphical_tools_example.py @@ -44,4 +44,11 @@ gudhi.plot_persistence_barcode(persistence) print("#####################################################################") print("Show diagram persistence example") -gudhi.plot_persistence_diagram(persistence) +pplot = gudhi.plot_persistence_diagram(persistence) +pplot.show() + +print("#####################################################################") +print("Show diagram persistence example with a confidence band") + +pplot = gudhi.plot_persistence_diagram(persistence, band_boot=0.2) +pplot.show() diff --git a/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py b/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py index 984dbf1b..3baebd17 100755 --- a/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py +++ b/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py @@ -39,6 +39,7 @@ parser = argparse.ArgumentParser(description='RipsComplex creation from ' parser.add_argument("-f", "--file", type=str, required=True) parser.add_argument("-e", "--max_edge_length", type=float, default=0.5) parser.add_argument("-d", "--max_dimension", type=int, default=1) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -61,4 +62,5 @@ print("betti_numbers()=") print(simplex_tree.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() diff --git a/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py index 4c21b98e..5951eedf 100755 --- a/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py +++ b/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py @@ -39,6 +39,7 @@ parser = argparse.ArgumentParser(description='RipsComplex creation from ' parser.add_argument("-f", "--file", type=str, required=True) parser.add_argument("-e", "--max_edge_length", type=float, default=0.5) parser.add_argument("-d", "--max_dimension", type=int, default=1) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -64,7 +65,8 @@ with open(args.file, 'r') as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() else: print(args.file, "is not a valid OFF file") diff --git a/src/cython/example/rips_persistence_diagram.py b/src/cython/example/rips_persistence_diagram.py index 4e5cd2c8..9bfea41c 100755 --- a/src/cython/example/rips_persistence_diagram.py +++ b/src/cython/example/rips_persistence_diagram.py @@ -39,4 +39,5 @@ simplex_tree = rips.create_simplex_tree(max_dimension=1) diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0) print("diag=", diag) -gudhi.plot_persistence_diagram(diag) +pplot = gudhi.plot_persistence_diagram(diag) +pplot.show() 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 4845eb47..6145e7f2 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 @@ -37,6 +37,7 @@ parser = argparse.ArgumentParser(description='TangentialComplex creation from ' '- Constructs a tangential complex with the ' 'points from the given OFF file') parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-b", "--band_boot", type=float, default=0.) parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') args = parser.parse_args() @@ -59,7 +60,8 @@ with open(args.file, 'r') as f: print(st.betti_numbers()) if args.no_diagram == False: - gudhi.plot_persistence_diagram(diag) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=args.band_boot) + pplot.show() else: print(args.file, "is not a valid OFF file") diff --git a/src/cython/gudhi.pyx.in b/src/cython/gudhi.pyx.in index 34d7c3b5..ed2d28cc 100644 --- a/src/cython/gudhi.pyx.in +++ b/src/cython/gudhi.pyx.in @@ -30,6 +30,7 @@ include "cython/rips_complex.pyx" include "cython/cubical_complex.pyx" include "cython/periodic_cubical_complex.pyx" include "cython/persistence_graphical_tools.py" +include "cython/reader_utils.pyx" include "cython/witness_complex.pyx" include "cython/strong_witness_complex.pyx" @GUDHI_CYTHON_ALPHA_COMPLEX@ diff --git a/src/cython/include/Reader_utils_interface.h b/src/cython/include/Reader_utils_interface.h new file mode 100644 index 00000000..b87b6cca --- /dev/null +++ b/src/cython/include/Reader_utils_interface.h @@ -0,0 +1,54 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2017 INRIA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INCLUDE_READER_UTILS_INTERFACE_H_ +#define INCLUDE_READER_UTILS_INTERFACE_H_ + +#include <gudhi/reader_utils.h> + +#include <iostream> +#include <vector> +#include <string> + +namespace Gudhi { + +// Redefine functions with a different name in order the original name can be used in the Python version. +std::vector<std::vector<double>> read_matrix_from_csv_file(const std::string& filename, + const char separator = ';') { + return read_lower_triangular_matrix_from_csv_file<double>(filename, separator); +} + +inline std::map<int, std::vector<std::pair<double, double>>> + read_pers_intervals_grouped_by_dimension(std::string const& filename) { + return read_persistence_intervals_grouped_by_dimension(filename); +} + +inline std::vector<std::pair<double, double>> + read_pers_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { + return read_persistence_intervals_in_dimension(filename, only_this_dim); +} + + +} // namespace Gudhi + + +#endif // INCLUDE_READER_UTILS_INTERFACE_H_ diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h index 6d813f4a..d06ee4bd 100644 --- a/src/cython/include/Rips_complex_interface.h +++ b/src/cython/include/Rips_complex_interface.h @@ -66,7 +66,7 @@ class Rips_complex_interface { } else { // Rips construction where values is a distance matrix Distance_matrix distances = - read_lower_triangular_matrix_from_csv_file<Simplex_tree_interface<>::Filtration_value>(file_name); + Gudhi::read_lower_triangular_matrix_from_csv_file<Simplex_tree_interface<>::Filtration_value>(file_name); rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(distances, threshold); } } diff --git a/src/cython/test/test_reader_utils.py b/src/cython/test/test_reader_utils.py new file mode 100755 index 00000000..25591fb3 --- /dev/null +++ b/src/cython/test/test_reader_utils.py @@ -0,0 +1,88 @@ +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Vincent Rouvreau + + Copyright (C) 2017 INRIA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2017 INRIA" +__license__ = "GPL v3" + + +def test_non_existing_csv_file(): + # Try to open a non existing file + matrix = gudhi.read_lower_triangular_matrix_from_csv_file(csv_file='pouetpouettralala.toubiloubabdou') + assert matrix == [] + +def test_full_square_distance_matrix_csv_file(): + # Create test file + test_file = open('full_square_distance_matrix.csv', 'w') + test_file.write('0;1;2;3;\n1;0;4;5;\n2;4;0;6;\n3;5;6;0;') + test_file.close() + matrix = gudhi.read_lower_triangular_matrix_from_csv_file(csv_file="full_square_distance_matrix.csv") + assert matrix == [[], [1.0], [2.0, 4.0], [3.0, 5.0, 6.0]] + +def test_lower_triangular_distance_matrix_csv_file(): + # Create test file + test_file = open('lower_triangular_distance_matrix.csv', 'w') + test_file.write('\n1,\n2,3,\n4,5,6,\n7,8,9,10,') + test_file.close() + matrix = gudhi.read_lower_triangular_matrix_from_csv_file(csv_file="lower_triangular_distance_matrix.csv", separator=",") + assert matrix == [[], [1.0], [2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0, 10.0]] + +def test_non_existing_persistence_file(): + # Try to open a non existing file + persistence = gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file='pouetpouettralala.toubiloubabdou') + assert persistence == [] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='pouetpouettralala.toubiloubabdou', only_this_dim=1) + assert persistence == [] + +def test_read_persistence_intervals_without_dimension(): + # Create test file + test_file = open('persistence_intervals_without_dimension.pers', 'w') + test_file.write('# Simple persistence diagram without dimension\n2.7 3.7\n9.6 14.\n34.2 34.974\n3. inf') + test_file.close() + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_without_dimension.pers') + assert persistence == [(2.7, 3.7), (9.6, 14.), (34.2, 34.974), (3., float('Inf'))] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_without_dimension.pers', only_this_dim=0) + assert persistence == [] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_without_dimension.pers', only_this_dim=1) + assert persistence == [] + persistence = gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file='persistence_intervals_without_dimension.pers') + assert persistence == {-1: [(2.7, 3.7), (9.6, 14.0), (34.2, 34.974), (3.0, float('Inf'))]} + +def test_read_persistence_intervals_with_dimension(): + # Create test file + test_file = open('persistence_intervals_with_dimension.pers', 'w') + test_file.write('# Simple persistence diagram with dimension\n0 2.7 3.7\n1 9.6 14.\n3 34.2 34.974\n1 3. inf') + test_file.close() + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_with_dimension.pers') + assert persistence == [(2.7, 3.7), (9.6, 14.), (34.2, 34.974), (3., float('Inf'))] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_with_dimension.pers', only_this_dim=0) + assert persistence == [(2.7, 3.7)] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_with_dimension.pers', only_this_dim=1) + assert persistence == [(9.6, 14.), (3., float('Inf'))] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_with_dimension.pers', only_this_dim=2) + assert persistence == [] + persistence = gudhi.read_persistence_intervals_in_dimension(persistence_file='persistence_intervals_with_dimension.pers', only_this_dim=3) + assert persistence == [(34.2, 34.974)] + persistence = gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file='persistence_intervals_with_dimension.pers') + assert persistence == {0: [(2.7, 3.7)], 1: [(9.6, 14.0), (3.0, float('Inf'))], 3: [(34.2, 34.974)]} |