From e7162cf121d5e1619ca4b7b54b9cef4d9ff1c9f7 Mon Sep 17 00:00:00 2001 From: cjamin Date: Tue, 16 May 2017 14:25:19 +0000 Subject: Add read_persistence_diagram_from_file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2439 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 026fbb0528343a15a46935ded3aaf13297afeff5 --- src/common/include/gudhi/reader_utils.h | 38 ++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 97a87edd..ceee8daf 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -2,7 +2,7 @@ * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * - * Author(s): Clement Maria, Pawel Dlotko + * Author(s): Clement Maria, Pawel Dlotko, Clement Jamin * * Copyright (C) 2014 INRIA * @@ -295,4 +295,40 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from return result; } // read_lower_triangular_matrix_from_csv_file +/** +Reads a file containing persistance intervals. +Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +**/ + +std::vector< std::pair > read_persistence_diagram_from_file(std::string const& filename) { + + std::vector< std::pair > result; + + std::ifstream in; + in.open(filename); + if (!in.is_open()) { +#ifdef DEBUG_TRACES + std::cerr << "File \"" << filename << "\" does not exist.\n"; +#endif // DEBUG_TRACES + return result; + } + + std::string line; + while (!in.eof()) { + getline(in, line); + if (line.length() != 0 && line[0] != '#') { + double numbers[4]; + int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); + result.push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); +#ifdef DEBUG_TRACES + std::cerr << numbers[n - 2] << " - " << numbers[n - 1] << "\n"; +#endif // DEBUG_TRACES + } + } + + in.close(); + return result; +} // read_diagram_from_file + + #endif // READER_UTILS_H_ -- cgit v1.2.3 From d6bb19de457fa74c84dbd6d8afa63074fefb4552 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 May 2017 08:47:16 +0000 Subject: Modify the way cmake handles utilities, examples, test and benchmarks with new options to activate/desactivate them. Move hypergenerator as a common utility. Move random point generation from hypergenerator in src/common/include/gudhi/random_point_generators.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/cmake_modules_for_gudhi@2442 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e2d13e4b0c09455fb604b684f6d71530352271eb --- CMakeLists.txt | 76 +++------ data/points/generator/CMakeLists.txt | 15 -- data/points/generator/README | 29 ---- data/points/generator/hypergenerator.cpp | 133 --------------- src/CMakeLists.txt | 34 ++-- src/cmake/modules/GUDHI_modules.cmake | 43 +++++ src/cmake/modules/GUDHI_user_version_target.cmake | 90 ++++++++++ src/cmake/modules/GUDHI_user_version_target.txt | 91 ---------- src/common/include/gudhi/random_point_generators.h | 32 ++++ src/common/utilities/CMakeLists.txt | 15 ++ src/common/utilities/README | 19 +++ src/common/utilities/hypergenerator.cpp | 189 +++++++++++++++++++++ 12 files changed, 430 insertions(+), 336 deletions(-) delete mode 100644 data/points/generator/CMakeLists.txt delete mode 100644 data/points/generator/hypergenerator.cpp create mode 100644 src/cmake/modules/GUDHI_modules.cmake create mode 100644 src/cmake/modules/GUDHI_user_version_target.cmake delete mode 100644 src/cmake/modules/GUDHI_user_version_target.txt create mode 100644 src/common/utilities/CMakeLists.txt create mode 100644 src/common/utilities/README create mode 100644 src/common/utilities/hypergenerator.cpp (limited to 'src/common/include') diff --git a/CMakeLists.txt b/CMakeLists.txt index 324f8648..360eb87a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,10 +10,6 @@ message("CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") enable_testing() -# For "make user_version" -include("${CMAKE_MODULE_PATH}/GUDHI_user_version_target.txt") -# For "make doxygen" -include(GUDHI_doxygen_target) # This variable is used by Cython CMakeLists.txt to know its path set(GUDHI_CYTHON_PATH "src/cython") # For third parties libraries management - To be done last as CGAL updates CMAKE_MODULE_PATH @@ -38,54 +34,34 @@ if (DEBUG_TRACES) add_definitions(-DDEBUG_TRACES) endif() -include_directories(src/common/include/) -include_directories(src/Alpha_complex/include/) -include_directories(src/Bitmap_cubical_complex/include/) -include_directories(src/Bottleneck_distance/include/) -include_directories(src/Contraction/include/) -include_directories(src/Hasse_complex/include/) -include_directories(src/Persistent_cohomology/include/) -include_directories(src/Rips_complex/include/) -include_directories(src/Simplex_tree/include/) -include_directories(src/Skeleton_blocker/include/) -include_directories(src/Spatial_searching/include/) -include_directories(src/Subsampling/include/) -include_directories(src/Tangential_complex/include/) -include_directories(src/Witness_complex/include/) +# Modules list can be found in CMAKE_MODULE_PATH/GUDHI_modules.cmake +include(GUDHI_modules) -add_subdirectory(src/common/example) -add_subdirectory(src/common/test) -add_subdirectory(src/Simplex_tree/test) -add_subdirectory(src/Simplex_tree/example) -add_subdirectory(src/Persistent_cohomology/test) -add_subdirectory(src/Persistent_cohomology/example) -add_subdirectory(src/Persistent_cohomology/benchmark) -add_subdirectory(src/Skeleton_blocker/test) -add_subdirectory(src/Skeleton_blocker/example) -add_subdirectory(src/Contraction/example) -add_subdirectory(src/Witness_complex/test) -add_subdirectory(src/Witness_complex/example) -add_subdirectory(src/Bitmap_cubical_complex/test) -add_subdirectory(src/Bitmap_cubical_complex/example) -add_subdirectory(src/Alpha_complex/example) -add_subdirectory(src/Alpha_complex/test) -add_subdirectory(src/Spatial_searching/example) -add_subdirectory(src/Spatial_searching/test) -add_subdirectory(src/Subsampling/example) -add_subdirectory(src/Subsampling/test) -add_subdirectory(src/Tangential_complex/example) -add_subdirectory(src/Tangential_complex/test) -add_subdirectory(src/Tangential_complex/benchmark) -add_subdirectory(src/Bottleneck_distance/example) -add_subdirectory(src/Bottleneck_distance/test) -add_subdirectory(src/Bottleneck_distance/benchmark) -add_subdirectory(src/Rips_complex/example) -add_subdirectory(src/Rips_complex/test) +# Include module headers +foreach(GUDHI_MODULE ${GUDHI_MODULES}) + if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/include/) + include_directories(src/${GUDHI_MODULE}/include/) + endif() +endforeach() -# data points generator -add_subdirectory(data/points/generator) +# Include module CMake subdirectories +# GUDHI_SUB_DIRECTORIES is managed in CMAKE_MODULE_PATH/GUDHI_modules.cmake +foreach(GUDHI_MODULE ${GUDHI_MODULES}) + foreach(GUDHI_SUB_DIRECTORY ${GUDHI_SUB_DIRECTORIES}) + if(EXISTS ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_SUB_DIRECTORY}/CMakeLists.txt) + add_subdirectory(src/${GUDHI_MODULE}/${GUDHI_SUB_DIRECTORY}/) + endif() + endforeach() +endforeach() add_subdirectory(src/GudhUI) -# specific for cython module -add_subdirectory(${GUDHI_CYTHON_PATH}) +if (NOT WITHOUT_GUDHI_PYTHON) + # specific for cython module + add_subdirectory(${GUDHI_CYTHON_PATH}) +endif() + +# For "make user_version" - Requires GUDHI_modules to be performed +include(GUDHI_user_version_target) +# For "make doxygen" - Requires GUDHI_user_version_target to be performed +include(GUDHI_doxygen_target) diff --git a/data/points/generator/CMakeLists.txt b/data/points/generator/CMakeLists.txt deleted file mode 100644 index 88d377a7..00000000 --- a/data/points/generator/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(data_points_generator) - -if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) - add_executable ( data_points_generator hypergenerator.cpp ) - target_link_libraries(data_points_generator ${Boost_SYSTEM_LIBRARY}) - add_test(NAME data_points_generator_on_sphere_1000_3_15.2 COMMAND $ - "on" "sphere" "onSphere.off" "1000" "3" "15.2") - add_test(NAME data_points_generator_in_sphere_100_2 COMMAND $ - "in" "sphere" "inSphere.off" "100" "2") - - # on cube is not available in CGAL - add_test(NAME data_points_generator_in_cube_10000_3_5.8 COMMAND $ - "in" "cube" "inCube.off" "10000" "3" "5.8") -endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) diff --git a/data/points/generator/README b/data/points/generator/README index 951bcfe1..3183a51f 100644 --- a/data/points/generator/README +++ b/data/points/generator/README @@ -1,32 +1,3 @@ -=========================== C++ generators ===================================== - -To build the C++ generators, run in a Terminal: - -cd /path-to-gudhi/ -cmake . -cd /path-to-data-generator/ -make - -======================= data_points_generator ================================== - -Example of use : - -*** Hyper sphere|cube generator - -./data_points_generator on sphere onSphere.off 1000 3 15.2 - - => generates a onSphere.off file with 1000 points randomized on a sphere of dimension 3 and radius 15.2 - -./data_points_generator in sphere inSphere.off 100 2 - - => generates a inSphere.off file with 100 points randomized in a sphere of dimension 2 (circle) and radius 1.0 (default) - -./data_points_generator in cube inCube.off 10000 3 5.8 - - => generates a inCube.off file with 10000 points randomized in a cube of dimension 3 and side 5.8 - -!! Warning: hypegenerator on cube is not available !! - ===================== aurelien_alvarez_surfaces_in_R8 ========================== This generator is written in Python. diff --git a/data/points/generator/hypergenerator.cpp b/data/points/generator/hypergenerator.cpp deleted file mode 100644 index 5831de18..00000000 --- a/data/points/generator/hypergenerator.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* 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) 2014 INRIA Saclay (France) - * - * 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 . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include // for std::ofstream -#include - -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef K::Point_d Point; - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " in|on sphere|cube off_file_name points_number[integer > 0] " << - "dimension[integer > 1] radius[double > 0.0 | default = 1.0]" << std::endl; - exit(-1); -} - -int main(int argc, char **argv) { - // program args management - if ((argc != 6) && (argc != 7)) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - int points_number = atoi(argv[4]); - if (points_number <= 0) { - std::cerr << "Error: " << argv[4] << " is not correct" << std::endl; - usage(argv[0]); - } - - int dimension = atoi(argv[5]); - if (dimension <= 0) { - std::cerr << "Error: " << argv[5] << " is not correct" << std::endl; - usage(argv[0]); - } - - double radius = 1.0; - if (argc == 7) { - radius = atof(argv[6]); - if (radius <= 0.0) { - std::cerr << "Error: " << argv[6] << " is not correct" << std::endl; - usage(argv[0]); - } - } - - bool in = false; - if (strcmp(argv[1], "in") == 0) { - in = true; - } else if (strcmp(argv[1], "on") != 0) { - std::cerr << "Error: " << argv[1] << " is not correct" << std::endl; - usage(argv[0]); - } - - bool sphere = false; - if (memcmp(argv[2], "sphere", sizeof("sphere")) == 0) { - sphere = true; - } else if (memcmp(argv[2], "cube", sizeof("cube")) != 0) { - std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; - usage(argv[0]); - } - - std::ofstream diagram_out(argv[3]); - if (dimension == 3) { - diagram_out << "OFF" << std::endl; - diagram_out << points_number << " 0 0" << std::endl; - } else { - diagram_out << "nOFF" << std::endl; - diagram_out << dimension << " " << points_number << " 0 0" << std::endl; - } - - if (diagram_out.is_open()) { - // Instanciate a random point generator - CGAL::Random rng(0); - // Generate "points_number" random points in a vector - std::vector points; - if (in) { - if (sphere) { - CGAL::Random_points_in_ball_d rand_it(dimension, radius, rng); - CGAL::cpp11::copy_n(rand_it, points_number, std::back_inserter(points)); - } else { - CGAL::Random_points_in_cube_d rand_it(dimension, radius, rng); - CGAL::cpp11::copy_n(rand_it, points_number, std::back_inserter(points)); - } - } else { // means "on" - if (sphere) { - CGAL::Random_points_on_sphere_d rand_it(dimension, radius, rng); - CGAL::cpp11::copy_n(rand_it, points_number, std::back_inserter(points)); - } else { - std::cerr << "Sorry: on cube is not available" << std::endl; - usage(argv[0]); - } - } - - for (auto thePoint : points) { - int i = 0; - for (; i < dimension - 1; i++) { - diagram_out << thePoint[i] << " "; - } - diagram_out << thePoint[i] << std::endl; // last point + Carriage Return - } - } else { - std::cerr << "Error: " << argv[3] << " cannot be opened" << std::endl; - usage(argv[0]); - } - - return 0; -} - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebcb6888..77a03c17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,9 @@ enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") +# To be done first - Modules list can be found in CMAKE_MODULE_PATH/GUDHI_modules.cmake +include(GUDHI_modules) + # For "make doxygen" set(GUDHI_USER_VERSION_DIR ${CMAKE_SOURCE_DIR}) include(GUDHI_doxygen_target) @@ -39,27 +42,22 @@ endif() # Gudhi compilation part include_directories(include) -add_subdirectory(example/common) -add_subdirectory(example/Simplex_tree) -add_subdirectory(example/Persistent_cohomology) -add_subdirectory(example/Skeleton_blocker) -add_subdirectory(example/Contraction) -add_subdirectory(example/Bitmap_cubical_complex) -add_subdirectory(example/Witness_complex) -add_subdirectory(example/Alpha_complex) -add_subdirectory(example/Rips_complex) -add_subdirectory(example/Spatial_searching) -add_subdirectory(example/Subsampling) -add_subdirectory(example/Tangential_complex) -add_subdirectory(example/Bottleneck_distance) - -# data points generator -add_subdirectory(data/points/generator) +# Include module CMake subdirectories +# GUDHI_SUB_DIRECTORIES is managed in CMAKE_MODULE_PATH/GUDHI_modules.cmake +foreach(GUDHI_MODULE ${GUDHI_MODULES}) + foreach(GUDHI_SUB_DIRECTORY ${GUDHI_SUB_DIRECTORIES}) + if(EXISTS ${CMAKE_SOURCE_DIR}/${GUDHI_SUB_DIRECTORY}/${GUDHI_MODULE}/CMakeLists.txt) + add_subdirectory(src/${GUDHI_MODULE}/${GUDHI_SUB_DIRECTORY}/) + endif(EXISTS ${CMAKE_SOURCE_DIR}/${GUDHI_SUB_DIRECTORY}/${GUDHI_MODULE}/CMakeLists.txt) + endforeach(GUDHI_SUB_DIRECTORY ${GUDHI_SUB_DIRECTORIES}) +endforeach(GUDHI_MODULE ${GUDHI_MODULES}) add_subdirectory(GudhUI) -# specific for cython module -add_subdirectory(${GUDHI_CYTHON_PATH}) +if (NOT WITHOUT_GUDHI_PYTHON) + # specific for cython module + add_subdirectory(${GUDHI_CYTHON_PATH}) +endif() #--------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------- diff --git a/src/cmake/modules/GUDHI_modules.cmake b/src/cmake/modules/GUDHI_modules.cmake new file mode 100644 index 00000000..6a26d7bf --- /dev/null +++ b/src/cmake/modules/GUDHI_modules.cmake @@ -0,0 +1,43 @@ +# A function to add a new module in GUDHI + +set(GUDHI_MODULES "") +function(add_gudhi_module file_path) + set(GUDHI_MODULES ${GUDHI_MODULES} ${file_path} PARENT_SCOPE) +endfunction(add_gudhi_module) + +# Add your new module in the list, order is not important + +add_gudhi_module(common) +add_gudhi_module(Alpha_complex) +add_gudhi_module(Bitmap_cubical_complex) +add_gudhi_module(Bottleneck_distance) +add_gudhi_module(Contraction) +add_gudhi_module(Hasse_complex) +add_gudhi_module(Persistent_cohomology) +add_gudhi_module(Rips_complex) +add_gudhi_module(Simplex_tree) +add_gudhi_module(Skeleton_blocker) +add_gudhi_module(Spatial_searching) +add_gudhi_module(Subsampling) +add_gudhi_module(Tangential_complex) +add_gudhi_module(Witness_complex) + +# message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") + +if (WITH_GUDHI_BENCHMARK) + set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};benchmark") +endif() +if (WITH_GUDHI_EXAMPLE) + set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};example") +endif() +if (NOT WITHOUT_GUDHI_TEST) + set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};test") +endif() +if (NOT WITHOUT_GUDHI_UTILITIES) + set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};utilities") +endif() + +message("++ GUDHI_SUB_DIRECTORIES list is:\"${GUDHI_SUB_DIRECTORIES}\"") + + + diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake new file mode 100644 index 00000000..a764e88a --- /dev/null +++ b/src/cmake/modules/GUDHI_user_version_target.cmake @@ -0,0 +1,90 @@ +# Some functionnalities requires CMake 2.8.11 minimum +if (NOT CMAKE_VERSION VERSION_LESS 2.8.11) + + # Definition of the custom target user_version + add_custom_target(user_version) + + if(DEFINED USER_VERSION_DIR) + # set the GUDHI_USER_VERSION_DIR with USER_VERSION_DIR defined by the user + set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${USER_VERSION_DIR}) + else() + # set the GUDHI_USER_VERSION_DIR with timestamp and Gudhi version number + string(TIMESTAMP DATE_AND_TIME "%Y-%m-%d-%H-%M-%S") + set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${DATE_AND_TIME}_GUDHI_${GUDHI_VERSION}) + endif() + + set(GUDHI_DOXYGEN_DEPENDENCY user_version) + + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + make_directory ${GUDHI_USER_VERSION_DIR} + COMMENT "user_version creation in ${GUDHI_USER_VERSION_DIR}") + + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/Conventions.txt ${GUDHI_USER_VERSION_DIR}/Conventions.txt) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/README ${GUDHI_USER_VERSION_DIR}/README) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/COPYING ${GUDHI_USER_VERSION_DIR}/COPYING) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/src/CMakeLists.txt ${GUDHI_USER_VERSION_DIR}/CMakeLists.txt) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/src/Doxyfile ${GUDHI_USER_VERSION_DIR}/Doxyfile) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfigVersion.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfigVersion.cmake.in) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfig.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfig.cmake.in) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/CMakeGUDHIVersion.txt ${GUDHI_USER_VERSION_DIR}/CMakeGUDHIVersion.txt) + + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/biblio ${GUDHI_USER_VERSION_DIR}/biblio) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/src/cython ${GUDHI_USER_VERSION_DIR}/cython) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/data ${GUDHI_USER_VERSION_DIR}/data) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/src/cmake ${GUDHI_USER_VERSION_DIR}/cmake) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI) + + set(GUDHI_DIRECTORIES "doc;example;concept") + set(GUDHI_INCLUDE_DIRECTORIES "include/gudhi;include/gudhi_patches") + + foreach(GUDHI_MODULE ${GUDHI_MODULES}) + foreach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) + # Find files + file(GLOB GUDHI_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_DIRECTORY}/*) + + foreach(GUDHI_FILE ${GUDHI_FILES}) + get_filename_component(GUDHI_FILE_NAME ${GUDHI_FILE} NAME) + # GUDHI_FILE can be a file or a directory + if(IS_DIRECTORY ${GUDHI_FILE}) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) + else() + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) + endif() + endforeach() + endforeach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) + + foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + # include files + file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_INCLUDE_DIRECTORY}/*) + + foreach(GUDHI_INCLUDE_FILE ${GUDHI_INCLUDE_FILES}) + get_filename_component(GUDHI_INCLUDE_FILE_NAME ${GUDHI_INCLUDE_FILE} NAME) + # GUDHI_INCLUDE_FILE can be a file or a directory + if(IS_DIRECTORY ${GUDHI_INCLUDE_FILE}) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_INCLUDE_DIRECTORY}/${GUDHI_INCLUDE_FILE_NAME}) + else() + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_INCLUDE_DIRECTORY}/${GUDHI_INCLUDE_FILE_NAME}) + endif() + endforeach() + endforeach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + + endforeach(GUDHI_MODULE ${GUDHI_MODULES}) + +endif() diff --git a/src/cmake/modules/GUDHI_user_version_target.txt b/src/cmake/modules/GUDHI_user_version_target.txt deleted file mode 100644 index ca6bcd34..00000000 --- a/src/cmake/modules/GUDHI_user_version_target.txt +++ /dev/null @@ -1,91 +0,0 @@ -# Some functionnalities requires CMake 2.8.11 minimum -if (NOT CMAKE_VERSION VERSION_LESS 2.8.11) - - # Definition of the custom target user_version - add_custom_target(user_version) - - if(DEFINED USER_VERSION_DIR) - # set the GUDHI_USER_VERSION_DIR with USER_VERSION_DIR defined by the user - set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${USER_VERSION_DIR}) - else() - # set the GUDHI_USER_VERSION_DIR with timestamp and Gudhi version number - string(TIMESTAMP DATE_AND_TIME "%Y-%m-%d-%H-%M-%S") - set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${DATE_AND_TIME}_GUDHI_${GUDHI_VERSION}) - endif() - - set(GUDHI_DOXYGEN_DEPENDENCY user_version) - - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - make_directory ${GUDHI_USER_VERSION_DIR} - COMMENT "user_version creation in ${GUDHI_USER_VERSION_DIR}") - - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/Conventions.txt ${GUDHI_USER_VERSION_DIR}/Conventions.txt) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/README ${GUDHI_USER_VERSION_DIR}/README) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/COPYING ${GUDHI_USER_VERSION_DIR}/COPYING) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/src/CMakeLists.txt ${GUDHI_USER_VERSION_DIR}/CMakeLists.txt) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/src/Doxyfile ${GUDHI_USER_VERSION_DIR}/Doxyfile) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfigVersion.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfigVersion.cmake.in) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfig.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfig.cmake.in) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/CMakeGUDHIVersion.txt ${GUDHI_USER_VERSION_DIR}/CMakeGUDHIVersion.txt) - - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/biblio ${GUDHI_USER_VERSION_DIR}/biblio) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/src/cython ${GUDHI_USER_VERSION_DIR}/cython) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/data ${GUDHI_USER_VERSION_DIR}/data) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/src/cmake ${GUDHI_USER_VERSION_DIR}/cmake) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI) - - set(GUDHI_MODULES "common;Alpha_complex;Bitmap_cubical_complex;Bottleneck_distance;Contraction;Hasse_complex;Persistent_cohomology;Rips_complex;Simplex_tree;Skeleton_blocker;Spatial_searching;Subsampling;Tangential_complex;Witness_complex") - set(GUDHI_DIRECTORIES "doc;example;concept") - set(GUDHI_INCLUDE_DIRECTORIES "include/gudhi;include/gudhi_patches") - - foreach(GUDHI_MODULE ${GUDHI_MODULES}) - foreach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) - # Find files - file(GLOB GUDHI_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_DIRECTORY}/*) - - foreach(GUDHI_FILE ${GUDHI_FILES}) - get_filename_component(GUDHI_FILE_NAME ${GUDHI_FILE} NAME) - # GUDHI_FILE can be a file or a directory - if(IS_DIRECTORY ${GUDHI_FILE}) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) - else() - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) - endif() - endforeach() - endforeach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) - - foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) - # include files - file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_INCLUDE_DIRECTORY}/*) - - foreach(GUDHI_INCLUDE_FILE ${GUDHI_INCLUDE_FILES}) - get_filename_component(GUDHI_INCLUDE_FILE_NAME ${GUDHI_INCLUDE_FILE} NAME) - # GUDHI_INCLUDE_FILE can be a file or a directory - if(IS_DIRECTORY ${GUDHI_INCLUDE_FILE}) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_INCLUDE_DIRECTORY}/${GUDHI_INCLUDE_FILE_NAME}) - else() - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_INCLUDE_DIRECTORY}/${GUDHI_INCLUDE_FILE_NAME}) - endif() - endforeach() - endforeach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) - - endforeach(GUDHI_MODULE ${GUDHI_MODULES}) - -endif() diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h index 2ec465ef..9df77760 100644 --- a/src/common/include/gudhi/random_point_generators.h +++ b/src/common/include/gudhi/random_point_generators.h @@ -281,6 +281,38 @@ std::vector generate_points_on_sphere_d(std::size_t nu return points; } +template +std::vector generate_points_in_ball_d(std::size_t num_points, int dim, double radius) { + typedef typename Kernel::Point_d Point; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_in_ball_d generator(dim, radius); + std::vector points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + Point p = *generator++; + points.push_back(p); + ++i; + } + return points; +} + +template +std::vector generate_points_in_cube_d(std::size_t num_points, int dim, double radius) { + typedef typename Kernel::Point_d Point; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_in_cube_d generator(dim, radius); + std::vector points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + Point p = *generator++; + points.push_back(p); + ++i; + } + return points; +} + template std::vector generate_points_on_two_spheres_d(std::size_t num_points, int dim, double radius, double distance_between_centers, diff --git a/src/common/utilities/CMakeLists.txt b/src/common/utilities/CMakeLists.txt new file mode 100644 index 00000000..88d377a7 --- /dev/null +++ b/src/common/utilities/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.6) +project(data_points_generator) + +if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) + add_executable ( data_points_generator hypergenerator.cpp ) + target_link_libraries(data_points_generator ${Boost_SYSTEM_LIBRARY}) + add_test(NAME data_points_generator_on_sphere_1000_3_15.2 COMMAND $ + "on" "sphere" "onSphere.off" "1000" "3" "15.2") + add_test(NAME data_points_generator_in_sphere_100_2 COMMAND $ + "in" "sphere" "inSphere.off" "100" "2") + + # on cube is not available in CGAL + add_test(NAME data_points_generator_in_cube_10000_3_5.8 COMMAND $ + "in" "cube" "inCube.off" "10000" "3" "5.8") +endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0) diff --git a/src/common/utilities/README b/src/common/utilities/README new file mode 100644 index 00000000..f2ece556 --- /dev/null +++ b/src/common/utilities/README @@ -0,0 +1,19 @@ +======================= data_points_generator ================================== + +Example of use : + +*** Hyper sphere|cube generator + +./data_points_generator on sphere onSphere.off 1000 3 15.2 + + => generates a onSphere.off file with 1000 points randomized on a sphere of dimension 3 and radius 15.2 + +./data_points_generator in sphere inSphere.off 100 2 + + => generates a inSphere.off file with 100 points randomized in a sphere of dimension 2 (circle) and radius 1.0 (default) + +./data_points_generator in cube inCube.off 10000 3 5.8 + + => generates a inCube.off file with 10000 points randomized in a cube of dimension 3 and side 5.8 + +!! Warning: hypegenerator on cube is not available !! diff --git a/src/common/utilities/hypergenerator.cpp b/src/common/utilities/hypergenerator.cpp new file mode 100644 index 00000000..0f310a13 --- /dev/null +++ b/src/common/utilities/hypergenerator.cpp @@ -0,0 +1,189 @@ +/* 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) 2014 INRIA Saclay (France) + * + * 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 . + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include // for std::ofstream +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef K::Point_d Point; + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " in|on sphere|cube off_file_name points_number[integer > 0] " << + "dimension[integer > 1] radius[double > 0.0 | default = 1.0]" << std::endl; + exit(-1); +} + +int main(int argc, char **argv) { + // program args management + if ((argc != 6) && (argc != 7)) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + int points_number = atoi(argv[4]); + if (points_number <= 0) { + std::cerr << "Error: " << argv[4] << " is not correct" << std::endl; + usage(argv[0]); + } + + int dimension = atoi(argv[5]); + if (dimension <= 0) { + std::cerr << "Error: " << argv[5] << " is not correct" << std::endl; + usage(argv[0]); + } + + double radius = 1.0; + if (argc == 7) { + radius = atof(argv[6]); + if (radius <= 0.0) { + std::cerr << "Error: " << argv[6] << " is not correct" << std::endl; + usage(argv[0]); + } + } + + bool in = false; + if (strcmp(argv[1], "in") == 0) { + in = true; + } else if (strcmp(argv[1], "on") != 0) { + std::cerr << "Error: " << argv[1] << " is not correct" << std::endl; + usage(argv[0]); + } + + enum class Data_shape { sphere, cube, curve, torus, klein, undefined } ; + + Data_shape shape = Data_shape::undefined; + if (memcmp(argv[2], "sphere", sizeof("sphere")) == 0) { + shape = Data_shape::sphere; + } else if (memcmp(argv[2], "cube", sizeof("cube")) == 0) { + shape = Data_shape::cube; + } else if (memcmp(argv[2], "curve", sizeof("curve")) == 0) { + shape = Data_shape::curve; + } else if (memcmp(argv[2], "torus", sizeof("torus")) == 0) { + shape = Data_shape::torus; + } else if (memcmp(argv[2], "klein", sizeof("klein")) == 0) { + shape = Data_shape::klein; + } else { + std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; + usage(argv[0]); + } + + std::ofstream diagram_out(argv[3]); + if (dimension == 3) { + diagram_out << "OFF" << std::endl; + diagram_out << points_number << " 0 0" << std::endl; + } else { + diagram_out << "nOFF" << std::endl; + diagram_out << dimension << " " << points_number << " 0 0" << std::endl; + } + + if (diagram_out.is_open()) { + // Generate "points_number" random points in a vector + std::vector points; + if (in) { + switch (shape) { + case Data_shape::sphere: + points = Gudhi::generate_points_in_ball_d(points_number, dimension, radius); + break; + case Data_shape::cube: + points = Gudhi::generate_points_in_ball_d(points_number, dimension, radius); + break; + case Data_shape::curve: + std::cerr << "Sorry: in curve is not available" << std::endl; + usage(argv[0]); + break; + case Data_shape::torus: + std::cerr << "Sorry: in torus is not available" << std::endl; + usage(argv[0]); + break; + case Data_shape::klein: + std::cerr << "Sorry: in klein is not available" << std::endl; + usage(argv[0]); + break; + default: + usage(argv[0]); + break; + } + } else { // means "on" + switch (shape) { + case Data_shape::sphere: + points = Gudhi::generate_points_on_sphere_d(points_number, dimension, radius); + break; + case Data_shape::cube: + std::cerr << "Sorry: on cube is not available" << std::endl; + usage(argv[0]); + break; + case Data_shape::curve: + points = Gudhi::generate_points_on_moment_curve(points_number, dimension, -radius/2., radius/2.); + break; + case Data_shape::torus: + if (dimension == 3) + points = Gudhi::generate_points_on_torus_3D(points_number, dimension, radius, radius/2.); + else + points = Gudhi::generate_points_on_torus_d(points_number, dimension, true); + break; + case Data_shape::klein: + switch (dimension) { + case 3: + points = Gudhi::generate_points_on_klein_bottle_3D(points_number, radius, radius/2., true); + break; + case 4: + points = Gudhi::generate_points_on_klein_bottle_4D(points_number, radius, radius/2., 0., true); + break; + case 5: + points = Gudhi::generate_points_on_klein_bottle_variant_5D(points_number, radius, radius/2., true); + break; + default: + std::cerr << "Sorry: on klein is only available for dimension 3, 4 and 5" << std::endl; + usage(argv[0]); + break; + } + break; + default: + usage(argv[0]); + break; + } + } + + for (auto thePoint : points) { + int i = 0; + for (; i < dimension - 1; i++) { + diagram_out << thePoint[i] << " "; + } + diagram_out << thePoint[i] << std::endl; // last point + Carriage Return + } + } else { + std::cerr << "Error: " << argv[3] << " cannot be opened" << std::endl; + usage(argv[0]); + } + + return 0; +} + -- cgit v1.2.3 From 269fa842c2eaeb7ddf8040abfd6c18d23ac767e9 Mon Sep 17 00:00:00 2001 From: cjamin Date: Tue, 23 May 2017 09:10:41 +0000 Subject: read_persistence_diagram_from_file now uses an output iterator git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2455 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3969666dcde3581a75789c5a4b62817dea553f9f --- .../example/bottleneck_read_file_example.cpp | 15 +++++++++++++-- src/common/include/gudhi/reader_utils.h | 17 ++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'src/common/include') diff --git a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp index 67bd27db..74c8d1ab 100644 --- a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp +++ b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp @@ -31,14 +31,25 @@ #include #include +struct Persistence_interval + : std::pair +{ + Persistence_interval(std::tuple data) + : std::pair(std::make_pair(std::get<1>(data), std::get<2>(data))) + {} +}; + int main(int argc, char** argv) { if (argc < 3) { std::cout << "To run this program please provide as an input two files with persistence diagrams. Each file " << "should contain a birth-death pair per line. Third, optional parameter is an error bound on a bottleneck" << " distance (set by default to zero). The program will now terminate \n"; } - std::vector< std::pair< double, double > > diag1 = read_persistence_diagram_from_file(argv[1]); - std::vector< std::pair< double, double > > diag2 = read_persistence_diagram_from_file(argv[2]); + std::vector diag1; + std::vector diag2; + read_persistence_diagram_from_file(argv[1], std::back_inserter(diag1)); + read_persistence_diagram_from_file(argv[2], std::back_inserter(diag2)); + double tolerance = 0.; if (argc == 4) { tolerance = atof(argv[3]); diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index ceee8daf..019a3db2 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -298,11 +298,11 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from /** Reads a file containing persistance intervals. Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth, death);` +where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ - -std::vector< std::pair > read_persistence_diagram_from_file(std::string const& filename) { - - std::vector< std::pair > result; +template +void read_persistence_diagram_from_file(std::string const& filename, OutputIterator out) { std::ifstream in; in.open(filename); @@ -310,7 +310,6 @@ std::vector< std::pair > read_persistence_diagram_from_file(std: #ifdef DEBUG_TRACES std::cerr << "File \"" << filename << "\" does not exist.\n"; #endif // DEBUG_TRACES - return result; } std::string line; @@ -319,7 +318,9 @@ std::vector< std::pair > read_persistence_diagram_from_file(std: if (line.length() != 0 && line[0] != '#') { double numbers[4]; int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); - result.push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); + //int field = (n == 4 ? static_cast(numbers[0]) : -1); + int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); #ifdef DEBUG_TRACES std::cerr << numbers[n - 2] << " - " << numbers[n - 1] << "\n"; #endif // DEBUG_TRACES @@ -327,8 +328,6 @@ std::vector< std::pair > read_persistence_diagram_from_file(std: } in.close(); - return result; -} // read_diagram_from_file - +} // read_persistence_diagram_from_file #endif // READER_UTILS_H_ -- cgit v1.2.3 From 71527e6ff81a7ac657f8a797a050bbcf7a131cb9 Mon Sep 17 00:00:00 2001 From: cjamin Date: Mon, 29 May 2017 16:22:49 +0000 Subject: Add 2 new variants of read_persistence_diagram_from_file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2463 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bd0dd2c981856c8e1a51b2b97ac10d9edd59f694 --- .../example/bottleneck_read_file_example.cpp | 6 +- src/common/include/gudhi/reader_utils.h | 85 ++++++++++++++++++++-- 2 files changed, 82 insertions(+), 9 deletions(-) (limited to 'src/common/include') diff --git a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp index 74c8d1ab..e26edd26 100644 --- a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp +++ b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp @@ -45,10 +45,8 @@ int main(int argc, char** argv) { "should contain a birth-death pair per line. Third, optional parameter is an error bound on a bottleneck" << " distance (set by default to zero). The program will now terminate \n"; } - std::vector diag1; - std::vector diag2; - read_persistence_diagram_from_file(argv[1], std::back_inserter(diag1)); - read_persistence_diagram_from_file(argv[2], std::back_inserter(diag2)); + std::vector> diag1 = read_persistence_diagram_from_file(argv[1], -1); + std::vector> diag2 = read_persistence_diagram_from_file(argv[2], -1); double tolerance = 0.; if (argc == 4) { diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 019a3db2..7b371afc 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -310,24 +310,99 @@ void read_persistence_diagram_from_file(std::string const& filename, OutputItera #ifdef DEBUG_TRACES std::cerr << "File \"" << filename << "\" does not exist.\n"; #endif // DEBUG_TRACES + return; } - std::string line; while (!in.eof()) { + std::string line; getline(in, line); if (line.length() != 0 && line[0] != '#') { double numbers[4]; int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); - //int field = (n == 4 ? static_cast(numbers[0]) : -1); - int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); - *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); + if (n >= 2) { + //int field = (n == 4 ? static_cast(numbers[0]) : -1); + int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); + } + } + } + + in.close(); +} // read_persistence_diagram_from_file + +/** +Reads a file containing persistance intervals. +Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +The return value is an `std::map[dim, std::vector[std::pair[birth, death]]]` +where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +**/ +std::map>> read_persistence_diagram_from_file(std::string const& filename) { + + std::map>> ret; + + std::ifstream in; + in.open(filename); + if (!in.is_open()) { #ifdef DEBUG_TRACES - std::cerr << numbers[n - 2] << " - " << numbers[n - 1] << "\n"; + std::cerr << "File \"" << filename << "\" does not exist.\n"; #endif // DEBUG_TRACES + return ret; + } + + while (!in.eof()) { + std::string line; + getline(in, line); + if (line.length() != 0 && line[0] != '#') { + double numbers[4]; + int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); + if (n >= 2) { + int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + ret[dim].push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); + } + } + } + + in.close(); + return ret; +} // read_persistence_diagram_from_file + + +/** +Reads a file containing persistance 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 `std::vector[std::pair[birth, death]]` +where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +**/ +std::vector> read_persistence_diagram_from_file(std::string const& filename, int only_this_dim) { + + std::vector> ret; + + std::ifstream in; + in.open(filename); + if (!in.is_open()) { +#ifdef DEBUG_TRACES + std::cerr << "File \"" << filename << "\" does not exist.\n"; +#endif // DEBUG_TRACES + return ret; + } + + while (!in.eof()) { + std::string line; + getline(in, line); + if (line.length() != 0 && line[0] != '#') { + double numbers[4]; + int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); + int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + if (n >= 2 && (only_this_dim == -1 || dim == only_this_dim)) + ret.push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); } } in.close(); + return ret; } // read_persistence_diagram_from_file #endif // READER_UTILS_H_ -- cgit v1.2.3 From 53abf1ac75eefcecc1391d140183a49588f0d2d2 Mon Sep 17 00:00:00 2001 From: cjamin Date: Wed, 31 May 2017 11:30:58 +0000 Subject: Fix doc and shorten code git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2485 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 97dcd51c0dc9cef00a655e5e0ad078de752eabe8 --- src/common/include/gudhi/reader_utils.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 7b371afc..df10d5a5 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -297,15 +297,14 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from /** Reads a file containing persistance intervals. -Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth, death);` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ template void read_persistence_diagram_from_file(std::string const& filename, OutputIterator out) { - std::ifstream in; - in.open(filename); + std::ifstream in(filename); if (!in.is_open()) { #ifdef DEBUG_TRACES std::cerr << "File \"" << filename << "\" does not exist.\n"; @@ -326,13 +325,11 @@ void read_persistence_diagram_from_file(std::string const& filename, OutputItera } } } - - in.close(); } // read_persistence_diagram_from_file /** Reads a file containing persistance intervals. -Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The return value is an `std::map[dim, std::vector[std::pair[birth, death]]]` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ @@ -340,8 +337,7 @@ std::map>> read_persistence_diagram_f std::map>> ret; - std::ifstream in; - in.open(filename); + std::ifstream in(filename); if (!in.is_open()) { #ifdef DEBUG_TRACES std::cerr << "File \"" << filename << "\" does not exist.\n"; @@ -362,14 +358,13 @@ std::map>> read_persistence_diagram_f } } - in.close(); return ret; } // read_persistence_diagram_from_file /** Reads a file containing persistance intervals. -Each line might contain 2, 3 or 4 values: [field] [dimension] birth death +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. @@ -380,8 +375,7 @@ std::vector> read_persistence_diagram_from_file(std::s std::vector> ret; - std::ifstream in; - in.open(filename); + std::ifstream in(filename); if (!in.is_open()) { #ifdef DEBUG_TRACES std::cerr << "File \"" << filename << "\" does not exist.\n"; @@ -401,7 +395,6 @@ std::vector> read_persistence_diagram_from_file(std::s } } - in.close(); return ret; } // read_persistence_diagram_from_file -- cgit v1.2.3 From 8457da40a4af813d6368cd85d1f60d2b2de52191 Mon Sep 17 00:00:00 2001 From: cjamin Date: Wed, 31 May 2017 11:36:20 +0000 Subject: Typo git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2486 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: dcc6134d95dea816a3c54a2a796535f384ccfc54 --- src/common/include/gudhi/reader_utils.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index df10d5a5..55a1e875 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -296,7 +296,7 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from } // read_lower_triangular_matrix_from_csv_file /** -Reads a file containing persistance intervals. +Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth, death);` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. @@ -328,7 +328,7 @@ void read_persistence_diagram_from_file(std::string const& filename, OutputItera } // read_persistence_diagram_from_file /** -Reads a file containing persistance intervals. +Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The return value is an `std::map[dim, std::vector[std::pair[birth, death]]]` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. @@ -363,7 +363,7 @@ std::map>> read_persistence_diagram_f /** -Reads a file containing persistance intervals. +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` -- cgit v1.2.3 From cbcf098dbc2af8f385216d74d6ffbbe08deaff66 Mon Sep 17 00:00:00 2001 From: cjamin Date: Wed, 31 May 2017 11:44:16 +0000 Subject: Fix doc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2487 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7be9a5da2a64835ff7558373e7a754647bc5b663 --- src/common/include/gudhi/reader_utils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 55a1e875..bb744b1c 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -330,7 +330,7 @@ void read_persistence_diagram_from_file(std::string const& filename, OutputItera /** Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death -The return value is an `std::map[dim, std::vector[std::pair[birth, death]]]` +The return value is an `std::map>>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ std::map>> read_persistence_diagram_from_file(std::string const& filename) { @@ -368,7 +368,7 @@ 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 `std::vector[std::pair[birth, death]]` +The return value is an `std::vector>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ std::vector> read_persistence_diagram_from_file(std::string const& filename, int only_this_dim) { -- cgit v1.2.3 From 66873d7ee6dd369dd3d8c1909d6376ed2bce4cc7 Mon Sep 17 00:00:00 2001 From: cjamin Date: Wed, 31 May 2017 11:54:55 +0000 Subject: Check if birth <= death git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2488 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fc7aeca7ca7cd1ec2e9a9263849ec34d4dfa8414 --- src/common/include/gudhi/reader_utils.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index bb744b1c..6a89ce90 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -24,6 +24,7 @@ #define READER_UTILS_H_ #include +#include #include @@ -321,6 +322,7 @@ void read_persistence_diagram_from_file(std::string const& filename, OutputItera if (n >= 2) { //int field = (n == 4 ? static_cast(numbers[0]) : -1); int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); } } @@ -353,6 +355,7 @@ std::map>> read_persistence_diagram_f int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); if (n >= 2) { int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); + GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); ret[dim].push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); } } @@ -391,7 +394,10 @@ std::vector> read_persistence_diagram_from_file(std::s int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); if (n >= 2 && (only_this_dim == -1 || dim == only_this_dim)) + { + GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); ret.push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); + } } } -- cgit v1.2.3 From 8493f7a38001930329ec6204e6b3e8dff1c67df1 Mon Sep 17 00:00:00 2001 From: cjamin Date: Thu, 1 Jun 2017 10:26:05 +0000 Subject: Use make_function_output_iterator to avoid code duplication git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2498 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7d9a9d3f72ef4af17f4a9b8263526df69498090c --- src/common/include/gudhi/reader_utils.h | 54 +++++---------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 6a89ce90..f0903acc 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -338,29 +339,9 @@ where `dim` is an `int`, `birth` a `double`, and `death` a `double`. std::map>> read_persistence_diagram_from_file(std::string const& filename) { std::map>> ret; - - std::ifstream in(filename); - if (!in.is_open()) { -#ifdef DEBUG_TRACES - std::cerr << "File \"" << filename << "\" does not exist.\n"; -#endif // DEBUG_TRACES - return ret; - } - - while (!in.eof()) { - std::string line; - getline(in, line); - if (line.length() != 0 && line[0] != '#') { - double numbers[4]; - int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); - if (n >= 2) { - int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); - GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); - ret[dim].push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); - } - } - } - + read_persistence_diagram_from_file( + filename, + boost::make_function_output_iterator([&ret](auto t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); return ret; } // read_persistence_diagram_from_file @@ -377,30 +358,9 @@ where `dim` is an `int`, `birth` a `double`, and `death` a `double`. std::vector> read_persistence_diagram_from_file(std::string const& filename, int only_this_dim) { std::vector> ret; - - std::ifstream in(filename); - if (!in.is_open()) { -#ifdef DEBUG_TRACES - std::cerr << "File \"" << filename << "\" does not exist.\n"; -#endif // DEBUG_TRACES - return ret; - } - - while (!in.eof()) { - std::string line; - getline(in, line); - if (line.length() != 0 && line[0] != '#') { - double numbers[4]; - int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); - int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); - if (n >= 2 && (only_this_dim == -1 || dim == only_this_dim)) - { - GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); - ret.push_back(std::make_pair(numbers[n - 2], numbers[n - 1])); - } - } - } - + read_persistence_diagram_from_file( + filename, + boost::make_function_output_iterator([&ret](auto t) { ret.emplace_back(get<1>(t), get<2>(t)); })); return ret; } // read_persistence_diagram_from_file -- cgit v1.2.3 From 05de4e9f4ed8f74e53a11455bc50470beba908eb Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 9 Jun 2017 09:40:52 +0000 Subject: Remove boost date_time dependencies git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/boost_system_no_deprecated_test@2529 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: daa13fc0046ffdd72577bb1b399fcbdc8ef5033c --- src/Tangential_complex/benchmark/CMakeLists.txt | 3 +-- src/Tangential_complex/example/CMakeLists.txt | 4 ++-- src/Tangential_complex/test/CMakeLists.txt | 2 +- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/common/include/gudhi/Clock.h | 18 +++++++++--------- 5 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src/common/include') diff --git a/src/Tangential_complex/benchmark/CMakeLists.txt b/src/Tangential_complex/benchmark/CMakeLists.txt index 8cb16e8c..8729e394 100644 --- a/src/Tangential_complex/benchmark/CMakeLists.txt +++ b/src/Tangential_complex/benchmark/CMakeLists.txt @@ -3,8 +3,7 @@ project(Tangential_complex_benchmark) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) add_executable(Tangential_complex_benchmark benchmark_tc.cpp) - target_link_libraries(Tangential_complex_benchmark - ${Boost_DATE_TIME_LIBRARY} ${CGAL_LIBRARY}) + target_link_libraries(Tangential_complex_benchmark ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Tangential_complex_benchmark ${TBB_LIBRARIES}) endif(TBB_FOUND) diff --git a/src/Tangential_complex/example/CMakeLists.txt b/src/Tangential_complex/example/CMakeLists.txt index 45c7642b..16d1339d 100644 --- a/src/Tangential_complex/example/CMakeLists.txt +++ b/src/Tangential_complex/example/CMakeLists.txt @@ -3,9 +3,9 @@ project(Tangential_complex_examples) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) add_executable( Tangential_complex_example_basic example_basic.cpp ) - target_link_libraries(Tangential_complex_example_basic ${CGAL_LIBRARY} ${Boost_DATE_TIME_LIBRARY}) + target_link_libraries(Tangential_complex_example_basic ${CGAL_LIBRARY}) add_executable( Tangential_complex_example_with_perturb example_with_perturb.cpp ) - target_link_libraries(Tangential_complex_example_with_perturb ${CGAL_LIBRARY} ${Boost_DATE_TIME_LIBRARY}) + target_link_libraries(Tangential_complex_example_with_perturb ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Tangential_complex_example_basic ${TBB_LIBRARIES}) target_link_libraries(Tangential_complex_example_with_perturb ${TBB_LIBRARIES}) diff --git a/src/Tangential_complex/test/CMakeLists.txt b/src/Tangential_complex/test/CMakeLists.txt index 63e51c3e..1948c8f6 100644 --- a/src/Tangential_complex/test/CMakeLists.txt +++ b/src/Tangential_complex/test/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) include(GUDHI_test_coverage) add_executable( Tangential_complex_test_TC test_tangential_complex.cpp ) - target_link_libraries(Tangential_complex_test_TC ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_DATE_TIME_LIBRARY}) + target_link_libraries(Tangential_complex_test_TC ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) if (TBB_FOUND) target_link_libraries(Tangential_complex_test_TC ${TBB_LIBRARIES}) endif() diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 2be79ee4..8f486118 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -1,6 +1,6 @@ # This files manage third party libraries required by GUDHI -find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework date_time program_options thread) +find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h index 77f196ca..eff48e41 100644 --- a/src/common/include/gudhi/Clock.h +++ b/src/common/include/gudhi/Clock.h @@ -23,9 +23,9 @@ #ifndef CLOCK_H_ #define CLOCK_H_ -#include - +#include #include +#include namespace Gudhi { @@ -33,20 +33,20 @@ class Clock { public: // Construct and start the timer Clock(const std::string& msg_ = std::string()) - : startTime(boost::posix_time::microsec_clock::local_time()), + : startTime(std::chrono::system_clock::now()), end_called(false), msg(msg_) { } // Restart the timer void begin() const { end_called = false; - startTime = boost::posix_time::microsec_clock::local_time(); + startTime = std::chrono::system_clock::now(); } // Stop the timer void end() const { end_called = true; - endTime = boost::posix_time::microsec_clock::local_time(); + endTime = std::chrono::system_clock::now(); } std::string message() const { @@ -71,15 +71,15 @@ class Clock { // - or now otherwise. In this case, the timer is not stopped. double num_seconds() const { if (!end_called) { - auto end = boost::posix_time::microsec_clock::local_time(); - return (end - startTime).total_milliseconds() / 1000.; + auto end = std::chrono::system_clock::now(); + return std::chrono::duration_cast(end-startTime).count() / 1000.; } else { - return (endTime - startTime).total_milliseconds() / 1000.; + return std::chrono::duration_cast(endTime-startTime).count() / 1000.; } } private: - mutable boost::posix_time::ptime startTime, endTime; + mutable std::chrono::time_point startTime, endTime; mutable bool end_called; std::string msg; }; -- cgit v1.2.3 From 3a7ffc0bfec712cb586d5c7ea154a4fd20be1a39 Mon Sep 17 00:00:00 2001 From: cjamin Date: Fri, 9 Jun 2017 10:32:48 +0000 Subject: Change names and adapt example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2531 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 833a51dd03ddccca38c6011834bb58667d63ccbf --- .../example/bottleneck_read_file_example.cpp | 4 ++-- src/common/include/gudhi/reader_utils.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/common/include') diff --git a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp index de8c7f9d..94d9a148 100644 --- a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp +++ b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp @@ -35,8 +35,8 @@ int main(int argc, char** argv) { "should contain a birth-death pair per line. Third, optional parameter is an error bound on a bottleneck" << " distance (set by default to zero). The program will now terminate \n"; } - std::vector> diag1 = read_persistence_diagram_from_file(argv[1], -1); - std::vector> diag2 = read_persistence_diagram_from_file(argv[2], -1); + std::vector> diag1 = read_persistence_intervals_in_dimension(argv[1]); + std::vector> diag2 = read_persistence_intervals_in_dimension(argv[2]); double tolerance = 0.; if (argc == 4) { diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index f0903acc..62b479ac 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -304,7 +304,7 @@ The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ template -void read_persistence_diagram_from_file(std::string const& filename, OutputIterator out) { +void read_persistence_intervals_and_dimension(std::string const& filename, OutputIterator out) { std::ifstream in(filename); if (!in.is_open()) { @@ -336,10 +336,10 @@ Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The return value is an `std::map>>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ -std::map>> read_persistence_diagram_from_file(std::string const& filename) { +std::map>> read_persistence_intervals_grouped_by_dimension(std::string const& filename) { std::map>> ret; - read_persistence_diagram_from_file( + read_persistence_intervals_and_dimension( filename, boost::make_function_output_iterator([&ret](auto t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); return ret; @@ -355,10 +355,10 @@ If `only_this_dim` is >= 0, only the lines where dimension = `only_this_dim` The return value is an `std::vector>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. **/ -std::vector> read_persistence_diagram_from_file(std::string const& filename, int only_this_dim) { +std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { std::vector> ret; - read_persistence_diagram_from_file( + read_persistence_intervals_and_dimension( filename, boost::make_function_output_iterator([&ret](auto t) { ret.emplace_back(get<1>(t), get<2>(t)); })); return ret; -- cgit v1.2.3 From 4918b9c752a2d269678791dc4772ae9276539051 Mon Sep 17 00:00:00 2001 From: cjamin Date: Fri, 9 Jun 2017 10:42:12 +0000 Subject: Throw exceptions if file not found git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2533 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b412f432aeac6aef07ac2d9d65d50dc8f508c2e6 --- src/common/include/gudhi/reader_utils.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 62b479ac..35af09bd 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -94,7 +94,10 @@ template< typename Graph_t, typename Filtration_value, typename Vertex_handle > Graph_t read_graph(std::string file_name) { std::ifstream in_(file_name.c_str(), std::ios::in); if (!in_.is_open()) { - std::cerr << "Unable to open file " << file_name << std::endl; + std::string error_str("read_graph - Unable to open file "); + error_str.append(file_name); + std::cerr << error_str << std::endl; + throw std::invalid_argument(error_str); } typedef std::pair< Vertex_handle, Vertex_handle > Edge_t; @@ -308,10 +311,10 @@ void read_persistence_intervals_and_dimension(std::string const& filename, Outpu std::ifstream in(filename); if (!in.is_open()) { -#ifdef DEBUG_TRACES - std::cerr << "File \"" << filename << "\" does not exist.\n"; -#endif // DEBUG_TRACES - return; + std::string error_str("read_persistence_intervals_and_dimension - Unable to open file "); + error_str.append(filename); + std::cerr << error_str << std::endl; + throw std::invalid_argument(error_str); } while (!in.eof()) { -- cgit v1.2.3 From 7260c86a2158b0df3f33b49f314201dd51044563 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 9 Jun 2017 12:20:12 +0000 Subject: Rewrite Contraction and Skeleton blocker time display using Gudhi::Clock git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/boost_system_no_deprecated_test@2535 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e2b5c1e152fd7bdca9d07db0390944409942ba53 --- src/Contraction/example/Garland_heckbert.cpp | 5 +++++ src/Contraction/example/Rips_contraction.cpp | 5 +++++ src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp | 3 +++ src/common/include/gudhi/Clock.h | 2 +- 4 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/common/include') diff --git a/src/Contraction/example/Garland_heckbert.cpp b/src/Contraction/example/Garland_heckbert.cpp index 2b0dc973..f0cde95e 100644 --- a/src/Contraction/example/Garland_heckbert.cpp +++ b/src/Contraction/example/Garland_heckbert.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -164,6 +165,8 @@ int main(int argc, char *argv[]) { int num_contractions = atoi(argv[3]); + Gudhi::Clock contraction_chrono("Time to simplify and enumerate simplices"); + // constructs the contractor object with Garland Heckbert policies. Complex_contractor contractor(complex, new GH_cost(complex), @@ -179,6 +182,8 @@ int main(int argc, char *argv[]) { complex.num_edges() << " edges and " << complex.num_triangles() << " triangles." << std::endl; + std::cout << contraction_chrono; + // write simplified complex Gudhi::skeleton_blocker::Skeleton_blocker_off_writer off_writer(argv[2], complex); diff --git a/src/Contraction/example/Rips_contraction.cpp b/src/Contraction/example/Rips_contraction.cpp index 1b97f877..501b0e87 100644 --- a/src/Contraction/example/Rips_contraction.cpp +++ b/src/Contraction/example/Rips_contraction.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -67,6 +68,8 @@ int main(int argc, char *argv[]) { build_rips(complex, atof(argv[2])); + Gudhi::Clock contraction_chrono("Time to simplify and enumerate simplices"); + std::cout << "Initial complex has " << complex.num_vertices() << " vertices and " << complex.num_edges() << " edges" << std::endl; @@ -87,6 +90,8 @@ int main(int argc, char *argv[]) { complex.num_blockers() << " blockers and " << num_simplices << " simplices" << std::endl; + std::cout << contraction_chrono; + return EXIT_SUCCESS; } diff --git a/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp b/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp index 4a0044e1..08ff0264 100644 --- a/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp +++ b/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -45,6 +46,7 @@ Complex build_complete_complex(int n) { } int main(int argc, char *argv[]) { + Gudhi::Clock skbl_chrono("Time to build the complete complex, enumerate simplices and Euler Characteristic"); const int n = 15; // build a full complex with n vertices and 2^n-1 simplices @@ -78,5 +80,6 @@ int main(int argc, char *argv[]) { std::cout << "Saw " << num_vertices << " vertices, " << num_edges << " edges and " << num_simplices << " simplices" << std::endl; std::cout << "The Euler Characteristic is " << euler << std::endl; + std::cout << skbl_chrono; return EXIT_SUCCESS; } diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h index eff48e41..b83de2f5 100644 --- a/src/common/include/gudhi/Clock.h +++ b/src/common/include/gudhi/Clock.h @@ -62,7 +62,7 @@ class Clock { if (!clock.msg.empty()) stream << clock.msg << ": "; - stream << clock.num_seconds() << "s"; + stream << clock.num_seconds() << "s\n"; return stream; } -- cgit v1.2.3 From a6b6f91bfd5a86ee88297b27f18c2bc7d38f6db4 Mon Sep 17 00:00:00 2001 From: cjamin Date: Wed, 14 Jun 2017 07:45:09 +0000 Subject: Remove birth<=death check (should be done by the caller if necessary) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2544 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ce50159f4bf779a2a42d357cf1c2aa290feaf9b9 --- src/common/include/gudhi/reader_utils.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 35af09bd..8df20dcc 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -305,6 +305,7 @@ Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth, death);` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +Note: the function does not check that birth <= death. **/ template void read_persistence_intervals_and_dimension(std::string const& filename, OutputIterator out) { @@ -326,7 +327,6 @@ void read_persistence_intervals_and_dimension(std::string const& filename, Outpu if (n >= 2) { //int field = (n == 4 ? static_cast(numbers[0]) : -1); int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); - GUDHI_CHECK(numbers[n - 2] <= numbers[n - 1], "Error: birth > death."); *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); } } @@ -338,6 +338,7 @@ Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The return value is an `std::map>>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +Note: the function does not check that birth <= death. **/ std::map>> read_persistence_intervals_grouped_by_dimension(std::string const& filename) { @@ -357,6 +358,7 @@ 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 `std::vector>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +Note: the function does not check that birth <= death. **/ std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { -- cgit v1.2.3 From cdb39c39a60fe06009168c1ecb1d4ce5de0bed8c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 16 Jun 2017 09:31:43 +0000 Subject: Fix auto lambda (requires C++14) compilation issue git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/read_persistence_from_file@2550 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: df64cfdde77500b06f00432a1d1532518cd4dd37 --- src/common/include/gudhi/reader_utils.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 8df20dcc..f1684d78 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -25,8 +25,8 @@ #include #include -#include +#include #include #include @@ -340,12 +340,12 @@ The return value is an `std::map>>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. **/ -std::map>> read_persistence_intervals_grouped_by_dimension(std::string const& filename) { +inline std::map>> read_persistence_intervals_grouped_by_dimension(std::string const& filename) { std::map>> ret; read_persistence_intervals_and_dimension( filename, - boost::make_function_output_iterator([&ret](auto t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); + boost::make_function_output_iterator([&ret](std::tuple t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); return ret; } // read_persistence_diagram_from_file @@ -360,12 +360,12 @@ The return value is an `std::vector>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. **/ -std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { +inline std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { std::vector> ret; read_persistence_intervals_and_dimension( filename, - boost::make_function_output_iterator([&ret](auto t) { ret.emplace_back(get<1>(t), get<2>(t)); })); + boost::make_function_output_iterator([&ret](std::tuple t) { ret.emplace_back(get<1>(t), get<2>(t)); })); return ret; } // read_persistence_diagram_from_file -- cgit v1.2.3 From a4b7d528893f992115711225c7d4396de55c6c58 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 4 Jul 2017 13:37:29 +0000 Subject: Add Gudhi namespace for reader_utils Add confidence band in persistence_graphical_tools.py Persistence_diagram returns a plot that is no more showed. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/persistence_diagram_improvement@2582 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4125f4f525057e89c8b0d5d164ea0b9d1df1bd72 --- .../example/bottleneck_read_file_example.cpp | 4 ++-- .../example/rips_distance_matrix_persistence.cpp | 2 +- ..._rips_complex_from_csv_distance_matrix_file.cpp | 2 +- src/Rips_complex/test/test_rips_complex.cpp | 2 +- src/common/include/gudhi/reader_utils.h | 10 +++++++--- src/common/test/test_distance_matrix_reader.cpp | 4 ++-- src/cython/cython/persistence_graphical_tools.py | 23 +++++++++++++++------- .../doc/persistence_graphical_tools_user.rst | 10 ++++++---- ...ex_diagram_persistence_from_off_file_example.py | 4 +++- 9 files changed, 39 insertions(+), 22 deletions(-) (limited to 'src/common/include') 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> diag1 = read_persistence_intervals_in_dimension(argv[1]); - std::vector> diag2 = read_persistence_intervals_in_dimension(argv[2]); + std::vector> diag1 = Gudhi::read_persistence_intervals_in_dimension(argv[1]); + std::vector> 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(csv_matrix_file); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file(csv_matrix_file); Rips_complex rips_complex_from_file(distances, threshold); // Construct the Rips complex in a Simplex Tree 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(csv_file_name); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file(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(csv_file_name); + Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file(csv_file_name); Rips_complex rips_complex_from_file(distances, rips_threshold); const int DIMENSION_1 = 1; diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index f1684d78..8e99acfc 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -37,6 +37,8 @@ #include #include // for pair +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. @@ -331,7 +333,7 @@ void read_persistence_intervals_and_dimension(std::string const& filename, Outpu } } } -} // read_persistence_diagram_from_file +} // read_persistence_diagram_from_file /** Reads a file containing persistence intervals. @@ -347,7 +349,7 @@ inline std::map>> read_persistence_in filename, boost::make_function_output_iterator([&ret](std::tuple t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); return ret; -} // read_persistence_diagram_from_file +} // read_persistence_diagram_from_file /** @@ -367,6 +369,8 @@ inline std::vector> read_persistence_intervals_in_dime filename, boost::make_function_output_iterator([&ret](std::tuple t) { ret.emplace_back(get<1>(t), get<2>(t)); })); return ret; -} // read_persistence_diagram_from_file +} // read_persistence_diagram_from_file + +} // 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("lower_triangular_distance_matrix.csv", + from_lower_triangular = Gudhi::read_lower_triangular_matrix_from_csv_file("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("full_square_distance_matrix.csv"); + from_full_square = Gudhi::read_lower_triangular_matrix_from_csv_file("full_square_distance_matrix.csv"); for (auto& i : from_full_square) { for (auto j : i) { std::cout << j << " "; diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index a984633e..70ff6001 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -5,7 +5,7 @@ import numpy as np (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 @@ -27,11 +27,13 @@ __author__ = "Vincent Rouvreau" __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 +47,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) """ @@ -108,16 +112,18 @@ def plot_persistence_barcode(persistence, alpha=0.6): plt.axis([axis_start, infinity, 0, ind]) plt.show() -def plot_persistence_diagram(persistence, alpha=0.6): - """This function plots the persistence diagram. +def plot_persistence_diagram(persistence, alpha=0.6, band_boot=0.): + """This function plots the persistence diagram with confidence band. :param persistence: The persistence to plot. :type persistence: list of tuples(dimension, tuple(birth, death)). :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 + :type band_boot: float. + :returns: plot -- A diagram plot of persistence. """ - (min_birth, max_death) = __min_birth_max_death(persistence) + (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 +137,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 +158,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/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst index cae18323..bc731f12 100644 --- a/src/cython/doc/persistence_graphical_tools_user.rst +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -51,16 +51,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) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=0.13) + pplot.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) + pplot = gudhi.plot_persistence_diagram(diag, band_boot=0.13) + 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") -- cgit v1.2.3 From 4832d865981bb74c8afc7240e953adc8f54c52b0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 6 Jul 2017 15:38:44 +0000 Subject: Plot functions now returns a plot that can be modified before to be shown Add confidence band in plot_persistence_diagram Cythonization of read_lower_triangular_matrix_from_csv_file and read_persistence_intervals functions Add Python tests of read functions git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/persistence_diagram_improvement@2590 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 522ec31e9ad3a9a688875612d246114704b8c74e --- src/common/include/gudhi/reader_utils.h | 2 +- src/cython/CMakeLists.txt | 2 +- src/cython/cython/persistence_graphical_tools.py | 4 +- src/cython/cython/reader_utils.pyx | 95 ++++++++++++++++++++++ src/cython/doc/pyplots/barcode_persistence.py | 2 +- src/cython/doc/pyplots/diagram_persistence.py | 8 +- ...ex_diagram_persistence_from_off_file_example.py | 4 +- ...ex_diagram_persistence_from_off_file_example.py | 5 +- ...ex_diagram_persistence_from_off_file_example.py | 5 +- .../example/gudhi_graphical_tools_example.py | 9 +- ...ersistence_from_distance_matrix_file_example.py | 4 +- src/cython/example/rips_persistence_diagram.py | 3 +- ...complex_plain_homology_from_off_file_example.py | 4 +- src/cython/gudhi.pyx.in | 1 + src/cython/include/Reader_utils_interface.h | 54 ++++++++++++ src/cython/include/Rips_complex_interface.h | 2 +- src/cython/test/test_reader_utils.py | 81 ++++++++++++++++++ 17 files changed, 267 insertions(+), 18 deletions(-) create mode 100644 src/cython/cython/reader_utils.pyx create mode 100644 src/cython/include/Reader_utils_interface.h create mode 100755 src/cython/test/test_reader_utils.py (limited to 'src/common/include') diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index 8e99acfc..f16ae61d 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -359,7 +359,7 @@ 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 `std::vector>` -where `dim` is an `int`, `birth` a `double`, and `death` a `double`. +where `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. **/ inline std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 99badffb..f427b3c5 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -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 diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py index 70ff6001..da709b8a 100755 --- a/src/cython/cython/persistence_graphical_tools.py +++ b/src/cython/cython/persistence_graphical_tools.py @@ -113,13 +113,13 @@ def plot_persistence_barcode(persistence, alpha=0.6): plt.show() def plot_persistence_diagram(persistence, alpha=0.6, band_boot=0.): - """This function plots the persistence diagram with confidence band. + """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 alpha: alpha value in [0.0, 1.0] for points and horizontal infinity line (default is 0.6). :type alpha: float. - :param band_boot: bootstrap band + :param band_boot: bootstrap band (not displayed if :math:`\leq` 0.) :type band_boot: float. :returns: plot -- A diagram plot of persistence. """ diff --git a/src/cython/cython/reader_utils.pyx b/src/cython/cython/reader_utils.pyx new file mode 100644 index 00000000..14976167 --- /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 . +""" + +__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), str.encode(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/doc/pyplots/barcode_persistence.py b/src/cython/doc/pyplots/barcode_persistence.py index c06ac5a7..b021049f 100755 --- a/src/cython/doc/pyplots/barcode_persistence.py +++ b/src/cython/doc/pyplots/barcode_persistence.py @@ -1,5 +1,5 @@ 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) diff --git a/src/cython/doc/pyplots/diagram_persistence.py b/src/cython/doc/pyplots/diagram_persistence.py index b4714fe3..56d6c50f 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() +pplot = gudhi.plot_persistence_diagram(diag, band_boot=0.13) +pplot.show() 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_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 . + */ + +#ifndef INCLUDE_READER_UTILS_INTERFACE_H_ +#define INCLUDE_READER_UTILS_INTERFACE_H_ + +#include + +#include +#include +#include + +namespace Gudhi { + +// Redefine functions with a different name in order the original name can be used in the Python version. +std::vector> read_matrix_from_csv_file(const std::string& filename, + const char separator = ';') { + return read_lower_triangular_matrix_from_csv_file(filename, separator); +} + +inline std::map>> + read_pers_intervals_grouped_by_dimension(std::string const& filename) { + return read_persistence_intervals_grouped_by_dimension(filename); +} + +inline std::vector> + 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::Filtration_value>(file_name); + Gudhi::read_lower_triangular_matrix_from_csv_file::Filtration_value>(file_name); rips_complex_ = new Rips_complex::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..517bf109 --- /dev/null +++ b/src/cython/test/test_reader_utils.py @@ -0,0 +1,81 @@ +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 . +""" + +__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=15) + assert persistence == [[2.7, 3.7], [9.6, 14.], [34.2, 34.974], [3., float('Inf')]] + 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=1) + # BUG !!! + assert persistence == [[2.7, 3.7], [9.6, 14.], [34.2, 34.974], [3., float('Inf')]] + 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)]} -- cgit v1.2.3 From 1129608c2add6f15538b3e281d75119f0e1bc8b0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 8 Aug 2017 12:48:40 +0000 Subject: Fix bug in read_persistence_intervals_in_dimension for only_this_dim Add unitary tests for read_persistence Add .clang-format to clang format new files git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@2601 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 28e870973f9ebd686d503246202fa6d6a549e9e3 --- src/.clang-format | 90 ++++++ src/common/include/gudhi/reader_utils.h | 93 +++--- src/common/test/CMakeLists.txt | 7 + src/common/test/README | 2 +- .../test/persistence_intervals_with_dimension.pers | 5 + .../test/persistence_intervals_with_field.pers | 4 + .../persistence_intervals_without_dimension.pers | 7 + .../test/test_persistence_intervals_reader.cpp | 321 +++++++++++++++++++++ 8 files changed, 478 insertions(+), 51 deletions(-) create mode 100644 src/.clang-format create mode 100644 src/common/test/persistence_intervals_with_dimension.pers create mode 100644 src/common/test/persistence_intervals_with_field.pers create mode 100644 src/common/test/persistence_intervals_without_dimension.pers create mode 100644 src/common/test/test_persistence_intervals_reader.cpp (limited to 'src/common/include') diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 00000000..dd4590c8 --- /dev/null +++ b/src/.clang-format @@ -0,0 +1,90 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never +... + diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index f1684d78..bda93f4f 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -1,5 +1,5 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ +/* 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): Clement Maria, Pawel Dlotko, Clement Jamin @@ -36,6 +36,7 @@ #include #include #include // for pair +#include // for std::make_tuple // Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented. // It is required for global functions and variables. @@ -52,7 +53,7 @@ * X21 X22 ... X2d
* etc
*/ -inline void read_points(std::string file_name, std::vector< std::vector< double > > & points) { +inline void read_points(std::string file_name, std::vector>& points) { std::ifstream in_file(file_name.c_str(), std::ios::in); if (!in_file.is_open()) { std::cerr << "Unable to open file " << file_name << std::endl; @@ -62,14 +63,13 @@ inline void read_points(std::string file_name, std::vector< std::vector< double std::string line; double x; while (getline(in_file, line)) { - std::vector< double > point; + std::vector point; std::istringstream iss(line); while (iss >> x) { point.push_back(x); } // Check for empty lines - if (!point.empty()) - points.push_back(point); + if (!point.empty()) points.push_back(point); } in_file.close(); } @@ -90,7 +90,7 @@ inline void read_points(std::string file_name, std::vector< std::vector< double * Every simplex must appear exactly once. * Simplices of dimension more than 1 are ignored. */ -template< typename Graph_t, typename Filtration_value, typename Vertex_handle > +template Graph_t read_graph(std::string file_name) { std::ifstream in_(file_name.c_str(), std::ios::in); if (!in_.is_open()) { @@ -100,10 +100,10 @@ Graph_t read_graph(std::string file_name) { throw std::invalid_argument(error_str); } - typedef std::pair< Vertex_handle, Vertex_handle > Edge_t; - std::vector< Edge_t > edges; - std::vector< Filtration_value > edges_fil; - std::map< Vertex_handle, Filtration_value > vertices; + typedef std::pair Edge_t; + std::vector edges; + std::vector edges_fil; + std::map vertices; std::string line; int dim; @@ -113,8 +113,7 @@ Graph_t read_graph(std::string file_name) { std::istringstream iss(line); while (iss >> dim) { switch (dim) { - case 0: - { + case 0: { iss >> u; iss >> fil; vertices[u] = fil; @@ -123,8 +122,7 @@ Graph_t read_graph(std::string file_name) { } break; } - case 1: - { + case 1: { iss >> u; iss >> v; iss >> fil; @@ -132,16 +130,13 @@ Graph_t read_graph(std::string file_name) { edges_fil.push_back(fil); break; } - default: - { - break; - } + default: { break; } } } } in_.close(); - if ((size_t) (max_h + 1) != vertices.size()) { + if ((size_t)(max_h + 1) != vertices.size()) { std::cerr << "Error: vertices must be labeled from 0 to n-1 \n"; } @@ -169,8 +164,8 @@ Graph_t read_graph(std::string file_name) { * Every simplex must appear exactly once. * Simplices of dimension more than 1 are ignored. */ -template< typename Vertex_handle, typename Filtration_value > -bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Filtration_value & fil) { +template +bool read_simplex(std::istream& in_, std::vector& simplex, Filtration_value& fil) { int dim = 0; if (!(in_ >> dim)) return false; Vertex_handle v; @@ -194,8 +189,8 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi * The key of a simplex is its position in the filtration order and also the number of its row in the file. * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the filtration has dimension Dimi, filtration value * fil1 and simplices with key ki1 ... kiDimi in its boundary.*/ -template< typename Simplex_key, typename Filtration_value > -bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundary, Filtration_value & fil) { +template +bool read_hasse_simplex(std::istream& in_, std::vector& boundary, Filtration_value& fil) { int dim; if (!(in_ >> dim)) return false; if (dim == 0) { @@ -214,7 +209,7 @@ bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundar /** * @brief Read a lower triangular distance matrix from a csv file. We assume that the .csv store the whole * (square) matrix. - * + * * @author Pawel Dlotko * * Square matrix file format:
@@ -231,13 +226,13 @@ bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundar * Dj1;Dj2;...;Dj(j-1);
* **/ -template< typename Filtration_value > -std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from_csv_file(const std::string& filename, - const char separator = ';') { +template +std::vector> read_lower_triangular_matrix_from_csv_file(const std::string& filename, + const char separator = ';') { #ifdef DEBUG_TRACES std::cout << "Using procedure read_lower_triangular_matrix_from_csv_file \n"; #endif // DEBUG_TRACES - std::vector< std::vector< Filtration_value > > result; + std::vector> result; std::ifstream in; in.open(filename.c_str()); if (!in.is_open()) { @@ -248,7 +243,7 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from // the first line is emtpy, so we ignore it: std::getline(in, line); - std::vector< Filtration_value > values_in_this_line; + std::vector values_in_this_line; result.push_back(values_in_this_line); int number_of_line = 0; @@ -256,11 +251,10 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from // first, read the file line by line to a string: while (std::getline(in, line)) { // if line is empty, break - if (line.size() == 0) - break; + if (line.size() == 0) break; // if the last element of a string is comma: - if (line[ line.size() - 1 ] == separator) { + if (line[line.size() - 1] == separator) { // then shrink the string by one line.pop_back(); } @@ -273,7 +267,7 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from // and now read the doubles. int number_of_entry = 0; - std::vector< Filtration_value > values_in_this_line; + std::vector values_in_this_line; while (iss.good()) { double entry; iss >> entry; @@ -282,7 +276,7 @@ std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from } ++number_of_entry; } - if (!values_in_this_line.empty())result.push_back(values_in_this_line); + if (!values_in_this_line.empty()) result.push_back(values_in_this_line); ++number_of_line; } in.close(); @@ -309,7 +303,6 @@ Note: the function does not check that birth <= death. **/ template void read_persistence_intervals_and_dimension(std::string const& filename, OutputIterator out) { - std::ifstream in(filename); if (!in.is_open()) { std::string error_str("read_persistence_intervals_and_dimension - Unable to open file "); @@ -325,13 +318,12 @@ void read_persistence_intervals_and_dimension(std::string const& filename, Outpu double numbers[4]; int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]); if (n >= 2) { - //int field = (n == 4 ? static_cast(numbers[0]) : -1); int dim = (n >= 3 ? static_cast(numbers[n - 3]) : -1); *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]); } } } -} // read_persistence_diagram_from_file +} /** Reads a file containing persistence intervals. @@ -340,33 +332,34 @@ The return value is an `std::map>>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. **/ -inline std::map>> read_persistence_intervals_grouped_by_dimension(std::string const& filename) { - +inline std::map>> read_persistence_intervals_grouped_by_dimension( + std::string const& filename) { std::map>> ret; read_persistence_intervals_and_dimension( - filename, - boost::make_function_output_iterator([&ret](std::tuple t) { ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); })); + filename, boost::make_function_output_iterator([&ret](std::tuple t) { + ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t))); + })); return ret; -} // read_persistence_diagram_from_file - +} /** 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` +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 `std::vector>` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. **/ -inline std::vector> read_persistence_intervals_in_dimension(std::string const& filename, int only_this_dim = -1) { - +inline std::vector> read_persistence_intervals_in_dimension(std::string const& filename, + int only_this_dim = -1) { std::vector> ret; read_persistence_intervals_and_dimension( - filename, - boost::make_function_output_iterator([&ret](std::tuple t) { ret.emplace_back(get<1>(t), get<2>(t)); })); + filename, boost::make_function_output_iterator([only_this_dim, &ret](std::tuple t) { + if (only_this_dim == get<0>(t) || only_this_dim == -1) ret.emplace_back(get<1>(t), get<2>(t)); + })); return ret; -} // read_persistence_diagram_from_file +} #endif // READER_UTILS_H_ diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 5aa426d7..de3e765a 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -9,10 +9,17 @@ target_link_libraries(Common_test_points_off_reader ${Boost_UNIT_TEST_FRAMEWORK_ add_executable ( Common_test_distance_matrix_reader test_distance_matrix_reader.cpp ) target_link_libraries(Common_test_distance_matrix_reader ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +add_executable ( Common_test_persistence_intervals_reader test_persistence_intervals_reader.cpp ) +target_link_libraries(Common_test_persistence_intervals_reader ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_with_dimension.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_with_field.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_without_dimension.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) gudhi_add_coverage_test(Common_test_points_off_reader) gudhi_add_coverage_test(Common_test_distance_matrix_reader) +gudhi_add_coverage_test(Common_test_persistence_intervals_reader) diff --git a/src/common/test/README b/src/common/test/README index f2a7eb5a..a8e6efe9 100644 --- a/src/common/test/README +++ b/src/common/test/README @@ -7,7 +7,7 @@ make To launch with details: *********************** -./dtoffrw_UT --report_level=detailed --log_level=all +./Common_test_points_off_reader --report_level=detailed --log_level=all ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/common/test/persistence_intervals_with_dimension.pers b/src/common/test/persistence_intervals_with_dimension.pers new file mode 100644 index 00000000..406748c8 --- /dev/null +++ b/src/common/test/persistence_intervals_with_dimension.pers @@ -0,0 +1,5 @@ +# Simple persistence diagram with dimension +0 2.7 3.7 +1 9.6 14. +3 34.2 34.974 +1 3. inf diff --git a/src/common/test/persistence_intervals_with_field.pers b/src/common/test/persistence_intervals_with_field.pers new file mode 100644 index 00000000..41dd9f1e --- /dev/null +++ b/src/common/test/persistence_intervals_with_field.pers @@ -0,0 +1,4 @@ +3 0 2.7 3.7 +3 1 9.6 14. +3 3 34.2 34.974 +3 1 3. inf diff --git a/src/common/test/persistence_intervals_without_dimension.pers b/src/common/test/persistence_intervals_without_dimension.pers new file mode 100644 index 00000000..76fa27f3 --- /dev/null +++ b/src/common/test/persistence_intervals_without_dimension.pers @@ -0,0 +1,7 @@ +# Simple persistence diagram without dimension +2.7 3.7 +9.6 14. +# Another comment +34.2 34.974 +3. inf +# End of file diff --git a/src/common/test/test_persistence_intervals_reader.cpp b/src/common/test/test_persistence_intervals_reader.cpp new file mode 100644 index 00000000..a06fff1e --- /dev/null +++ b/src/common/test/test_persistence_intervals_reader.cpp @@ -0,0 +1,321 @@ +/* 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 . + */ + +#include + +#include +#include +#include // for pair +#include +#include // for inf + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "persistence_intervals_reader" +#include + +using Persistence_intervals_by_dimension = std::map>>; +using Persistence_intervals = std::vector>; +// Test files with only 2 parameters (persistence birth and death) per line in file +BOOST_AUTO_TEST_CASE( persistence_intervals_without_dimension ) +{ + Persistence_intervals_by_dimension expected_intervals_by_dimension; + expected_intervals_by_dimension[-1].push_back(std::make_pair(2.7, 3.7)); + expected_intervals_by_dimension[-1].push_back(std::make_pair(9.6, 14.)); + expected_intervals_by_dimension[-1].push_back(std::make_pair(34.2, 34.974)); + expected_intervals_by_dimension[-1].push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals_by_dimension persistence_intervals_by_dimension = + 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) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n"; + for (auto map_iter : persistence_intervals_by_dimension) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension); + + Persistence_intervals expected_intervals_in_dimension; + expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7)); + expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.)); + expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974)); + expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals persistence_intervals_in_dimension = + 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) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension - read\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + 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", 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); + 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); + 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); + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); + +} +// Test files with 3 parameters (dimension birth death) per line in file +BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension ) +{ + Persistence_intervals_by_dimension expected_intervals_by_dimension; + expected_intervals_by_dimension[0].push_back(std::make_pair(2.7, 3.7)); + expected_intervals_by_dimension[1].push_back(std::make_pair(9.6, 14.)); + expected_intervals_by_dimension[3].push_back(std::make_pair(34.2, 34.974)); + expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals_by_dimension persistence_intervals_by_dimension = + 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) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n"; + for (auto map_iter : persistence_intervals_by_dimension) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension); + + Persistence_intervals expected_intervals_in_dimension; + expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7)); + expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.)); + expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974)); + expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals persistence_intervals_in_dimension = + 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) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_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); + + std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 0 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); + + expected_intervals_in_dimension.clear(); + 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::infinity())); + persistence_intervals_in_dimension = + 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) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 1 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + 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_with_dimension.pers", 2); + + std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 2 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_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); + + std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 3 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); + +} + +// Test files with 4 parameters (field dimension birth death) per line in file +BOOST_AUTO_TEST_CASE( persistence_intervals_with_field ) +{ + Persistence_intervals_by_dimension expected_intervals_by_dimension; + expected_intervals_by_dimension[0].push_back(std::make_pair(2.7, 3.7)); + expected_intervals_by_dimension[1].push_back(std::make_pair(9.6, 14.)); + expected_intervals_by_dimension[3].push_back(std::make_pair(34.2, 34.974)); + expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals_by_dimension persistence_intervals_by_dimension = + 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) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n"; + for (auto map_iter : persistence_intervals_by_dimension) { + std::cout << "key=" << map_iter.first; + for (auto vec_iter : map_iter.second) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + } + + BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension); + + Persistence_intervals expected_intervals_in_dimension; + expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7)); + expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.)); + expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974)); + expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits::infinity())); + + Persistence_intervals persistence_intervals_in_dimension = + 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) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_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_field.pers", 0); + + std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 0 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); + + expected_intervals_in_dimension.clear(); + 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::infinity())); + persistence_intervals_in_dimension = + 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) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 1 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + 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_with_field.pers", 2); + + std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 2 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_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_field.pers", 3); + + std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n"; + for (auto vec_iter : expected_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + std::cout << "\nread_persistence_intervals_in_dimension 3 - read\n"; + for (auto vec_iter : persistence_intervals_in_dimension) + std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] "; + + BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension); + +} -- cgit v1.2.3