multipers 2.3.0__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of multipers might be problematic. Click here for more details.

Files changed (188) hide show
  1. {multipers-2.3.0/multipers.egg-info → multipers-2.3.1}/PKG-INFO +1 -1
  2. multipers-2.3.0/multipers/ml/convolutions.py → multipers-2.3.1/multipers/filtrations/density.py +45 -2
  3. {multipers-2.3.0 → multipers-2.3.1}/multipers/filtrations/filtrations.py +2 -2
  4. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/Simplex_tree_multi_interface.h +1 -1
  5. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/One_critical_filtration.h +2 -1
  6. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/mma_interface_h0.h +1 -1
  7. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/mma_interface_matrix.h +8 -1
  8. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/naive_merge_tree.h +1 -1
  9. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/truc.h +82 -15
  10. {multipers-2.3.0 → multipers-2.3.1}/multipers/io.pyx +14 -11
  11. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/point_clouds.py +2 -2
  12. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/signed_measures.py +3 -3
  13. {multipers-2.3.0 → multipers-2.3.1}/multipers/mma_structures.pyx +0 -4
  14. {multipers-2.3.0 → multipers-2.3.1}/multipers/mma_structures.pyx.tp +0 -2
  15. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/approximation.h +4 -2
  16. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation.pyx +3 -1
  17. {multipers-2.3.0 → multipers-2.3.1}/multipers/plots.py +1 -1
  18. {multipers-2.3.0 → multipers-2.3.1}/multipers/simplex_tree_multi.pyx +97 -33
  19. {multipers-2.3.0 → multipers-2.3.1}/multipers/simplex_tree_multi.pyx.tp +13 -5
  20. {multipers-2.3.0 → multipers-2.3.1}/multipers/slicer.pxd +220 -100
  21. {multipers-2.3.0 → multipers-2.3.1}/multipers/slicer.pxd.tp +5 -2
  22. {multipers-2.3.0 → multipers-2.3.1}/multipers/slicer.pyx +484 -204
  23. {multipers-2.3.0 → multipers-2.3.1}/multipers/slicer.pyx.tp +16 -9
  24. {multipers-2.3.0 → multipers-2.3.1}/multipers/tensor/tensor.h +1 -1
  25. {multipers-2.3.0 → multipers-2.3.1}/multipers/torch/rips_density.py +1 -1
  26. {multipers-2.3.0 → multipers-2.3.1/multipers.egg-info}/PKG-INFO +1 -1
  27. {multipers-2.3.0 → multipers-2.3.1}/multipers.egg-info/SOURCES.txt +1 -1
  28. {multipers-2.3.0 → multipers-2.3.1}/pyproject.toml +1 -1
  29. {multipers-2.3.0 → multipers-2.3.1}/setup.py +1 -0
  30. {multipers-2.3.0 → multipers-2.3.1}/tests/test_signed_measure.py +0 -1
  31. {multipers-2.3.0 → multipers-2.3.1}/tests/test_simplextreemulti.py +10 -0
  32. {multipers-2.3.0 → multipers-2.3.1}/LICENSE +0 -0
  33. {multipers-2.3.0 → multipers-2.3.1}/MANIFEST.in +0 -0
  34. {multipers-2.3.0 → multipers-2.3.1}/README.md +0 -0
  35. {multipers-2.3.0 → multipers-2.3.1}/_tempita_grid_gen.py +0 -0
  36. {multipers-2.3.0 → multipers-2.3.1}/multipers/__init__.py +0 -0
  37. {multipers-2.3.0 → multipers-2.3.1}/multipers/_signed_measure_meta.py +0 -0
  38. {multipers-2.3.0 → multipers-2.3.1}/multipers/_slicer_meta.py +0 -0
  39. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/MOL2.py +0 -0
  40. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/UCR.py +0 -0
  41. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/__init__.py +0 -0
  42. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/graphs.py +0 -0
  43. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/immuno_regions.py +0 -0
  44. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/minimal_presentation_to_st_bf.py +0 -0
  45. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/pytorch2simplextree.py +0 -0
  46. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/shape3d.py +0 -0
  47. {multipers-2.3.0 → multipers-2.3.1}/multipers/data/synthetic.py +0 -0
  48. {multipers-2.3.0 → multipers-2.3.1}/multipers/distances.py +0 -0
  49. {multipers-2.3.0 → multipers-2.3.1}/multipers/filtration_conversions.pxd +0 -0
  50. {multipers-2.3.0 → multipers-2.3.1}/multipers/filtration_conversions.pxd.tp +0 -0
  51. {multipers-2.3.0 → multipers-2.3.1}/multipers/filtrations/__init__.py +0 -0
  52. {multipers-2.3.0 → multipers-2.3.1}/multipers/filtrations.pxd +0 -0
  53. {multipers-2.3.0 → multipers-2.3.1}/multipers/function_rips.pyx +0 -0
  54. {multipers-2.3.0 → multipers-2.3.1}/multipers/grids.pyx +0 -0
  55. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/Persistence_slices_interface.h +0 -0
  56. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/Simplex_tree_interface.h +0 -0
  57. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/cubical_to_boundary.h +0 -0
  58. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Bitmap_cubical_complex.h +0 -0
  59. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +0 -0
  60. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +0 -0
  61. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Debug_utils.h +0 -0
  62. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field.h +0 -0
  63. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field_operators.h +0 -0
  64. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field_shared.h +0 -0
  65. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field_small.h +0 -0
  66. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +0 -0
  67. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +0 -0
  68. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Z2_field.h +0 -0
  69. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Z2_field_operators.h +0 -0
  70. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Zp_field.h +0 -0
  71. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Zp_field_operators.h +0 -0
  72. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Fields/Zp_field_shared.h +0 -0
  73. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +0 -0
  74. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Matrix.h +0 -0
  75. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Multi_critical_filtration.h +0 -0
  76. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Multi_persistence/Box.h +0 -0
  77. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Multi_persistence/Line.h +0 -0
  78. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Off_reader.h +0 -0
  79. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +0 -0
  80. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +0 -0
  81. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +0 -0
  82. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +0 -0
  83. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +0 -0
  84. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +0 -0
  85. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +0 -0
  86. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +0 -0
  87. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +0 -0
  88. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +0 -0
  89. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +0 -0
  90. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +0 -0
  91. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +0 -0
  92. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +0 -0
  93. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +0 -0
  94. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +0 -0
  95. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +0 -0
  96. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +0 -0
  97. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +0 -0
  98. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +0 -0
  99. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +0 -0
  100. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +0 -0
  101. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +0 -0
  102. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +0 -0
  103. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +0 -0
  104. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +0 -0
  105. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +0 -0
  106. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +0 -0
  107. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +0 -0
  108. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +0 -0
  109. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +0 -0
  110. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +0 -0
  111. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +0 -0
  112. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +0 -0
  113. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +0 -0
  114. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +0 -0
  115. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +0 -0
  116. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Persistent_cohomology.h +0 -0
  117. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Points_off_io.h +0 -0
  118. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simple_object_pool.h +0 -0
  119. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +0 -0
  120. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +0 -0
  121. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +0 -0
  122. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +0 -0
  123. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +0 -0
  124. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +0 -0
  125. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +0 -0
  126. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +0 -0
  127. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree.h +0 -0
  128. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/Simplex_tree_multi.h +0 -0
  129. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/distance_functions.h +0 -0
  130. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/graph_simplicial_complex.h +0 -0
  131. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/persistence_interval.h +0 -0
  132. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/persistence_matrix_options.h +0 -0
  133. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/gudhi/reader_utils.h +0 -0
  134. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/mma_interface_coh.h +0 -0
  135. {multipers-2.3.0 → multipers-2.3.1}/multipers/gudhi/scc_io.h +0 -0
  136. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/__init__.py +0 -0
  137. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/accuracies.py +0 -0
  138. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/invariants_with_persistable.py +0 -0
  139. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/kernels.py +0 -0
  140. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/mma.py +0 -0
  141. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/one.py +0 -0
  142. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/sliced_wasserstein.py +0 -0
  143. {multipers-2.3.0 → multipers-2.3.1}/multipers/ml/tools.py +0 -0
  144. {multipers-2.3.0 → multipers-2.3.1}/multipers/mma_structures.pxd +0 -0
  145. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/diff_helpers.h +0 -0
  146. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/euler_characteristic.h +0 -0
  147. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/function_rips.h +0 -0
  148. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/hilbert_function.h +0 -0
  149. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/persistence_slices.h +0 -0
  150. {multipers-2.3.0 → multipers-2.3.1}/multipers/multi_parameter_rank_invariant/rank_invariant.h +0 -0
  151. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_edge_collapse.py +0 -0
  152. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/combinatory.h +0 -0
  153. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/debug.h +0 -0
  154. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/euler_curves.h +0 -0
  155. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/format_python-cpp.h +0 -0
  156. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/heap_column.h +0 -0
  157. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/images.h +0 -0
  158. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/list_column.h +0 -0
  159. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/list_column_2.h +0 -0
  160. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/ru_matrix.h +0 -0
  161. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/set_column.h +0 -0
  162. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +0 -0
  163. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/unordered_set_column.h +0 -0
  164. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/utilities.h +0 -0
  165. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/vector_column.h +0 -0
  166. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/vector_matrix.h +0 -0
  167. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/vineyards.h +0 -0
  168. {multipers-2.3.0 → multipers-2.3.1}/multipers/multiparameter_module_approximation/vineyards_trajectories.h +0 -0
  169. {multipers-2.3.0 → multipers-2.3.1}/multipers/pickle.py +0 -0
  170. {multipers-2.3.0 → multipers-2.3.1}/multipers/point_measure.pyx +0 -0
  171. {multipers-2.3.0 → multipers-2.3.1}/multipers/simplex_tree_multi.pxd +0 -0
  172. {multipers-2.3.0 → multipers-2.3.1}/multipers/tensor.pxd +0 -0
  173. {multipers-2.3.0 → multipers-2.3.1}/multipers/test.pyx +0 -0
  174. {multipers-2.3.0 → multipers-2.3.1}/multipers/tests/__init__.py +0 -0
  175. {multipers-2.3.0 → multipers-2.3.1}/multipers/torch/__init__.py +0 -0
  176. {multipers-2.3.0 → multipers-2.3.1}/multipers/torch/diff_grids.py +0 -0
  177. {multipers-2.3.0 → multipers-2.3.1}/multipers.egg-info/dependency_links.txt +0 -0
  178. {multipers-2.3.0 → multipers-2.3.1}/multipers.egg-info/requires.txt +0 -0
  179. {multipers-2.3.0 → multipers-2.3.1}/multipers.egg-info/top_level.txt +0 -0
  180. {multipers-2.3.0 → multipers-2.3.1}/setup.cfg +0 -0
  181. {multipers-2.3.0 → multipers-2.3.1}/tests/test_diff_helper.py +0 -0
  182. {multipers-2.3.0 → multipers-2.3.1}/tests/test_filtrations.py +0 -0
  183. {multipers-2.3.0 → multipers-2.3.1}/tests/test_hilbert_function.py +0 -0
  184. {multipers-2.3.0 → multipers-2.3.1}/tests/test_mma.py +0 -0
  185. {multipers-2.3.0 → multipers-2.3.1}/tests/test_point_clouds.py +0 -0
  186. {multipers-2.3.0 → multipers-2.3.1}/tests/test_python-cpp_conversion.py +0 -0
  187. {multipers-2.3.0 → multipers-2.3.1}/tests/test_signed_betti.py +0 -0
  188. {multipers-2.3.0 → multipers-2.3.1}/tests/test_slicer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multipers
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Multiparameter Topological Persistence for Machine Learning
5
5
  Author-email: David Loiseaux <david.lapous@proton.me>, Hannah Schreiber <hannah.schreiber@inria.fr>
6
6
  Maintainer-email: David Loiseaux <david.lapous@proton.me>
@@ -180,9 +180,10 @@ def _pts_convolution_pykeops(
180
180
 
181
181
 
182
182
  def gaussian_kernel(x_i, y_j, bandwidth):
183
+ D = x_i.shape[-1]
183
184
  exponent = -(((x_i - y_j) / bandwidth) ** 2).sum(dim=-1) / 2
184
185
  # float is necessary for some reason (pykeops fails)
185
- kernel = (exponent).exp() / (bandwidth * float(np.sqrt(2 * np.pi)))
186
+ kernel = (exponent).exp() / float((bandwidth*np.sqrt(2 * np.pi))**D)
186
187
  return kernel
187
188
 
188
189
 
@@ -339,7 +340,7 @@ class KDE:
339
340
  kernel *= w
340
341
  if return_kernel:
341
342
  return kernel
342
- density_estimation = kernel.sum(dim=0).ravel() / kernel.shape[0] # mean
343
+ density_estimation = kernel.sum(dim=0).squeeze() / kernel.shape[0] # mean
343
344
  return (
344
345
  self._backend.log(density_estimation)
345
346
  if self.return_log
@@ -497,6 +498,48 @@ class DTM:
497
498
  return DTMs
498
499
 
499
500
 
501
+ ## code taken from pykeops doc (https://www.kernel-operations.io/keops/_auto_benchmarks/benchmark_KNN.html)
502
+ class KNNmean:
503
+ def __init__(self, k: int, metric: str = "euclidean"):
504
+ self.k = k
505
+ self.metric = metric
506
+ self._KNN_fun = None
507
+ self._x = None
508
+
509
+ def fit(self, x):
510
+ if isinstance(x, np.ndarray):
511
+ from pykeops.numpy import Vi, Vj
512
+ else:
513
+ import torch
514
+
515
+ assert isinstance(x, torch.Tensor), "Backend has to be numpy or torch"
516
+ from pykeops.torch import Vi, Vj
517
+
518
+ D = x.shape[1]
519
+ X_i = Vi(0, D)
520
+ X_j = Vj(1, D)
521
+
522
+ # Symbolic distance matrix:
523
+ if self.metric == "euclidean":
524
+ D_ij = ((X_i - X_j) ** 2).sum(-1)
525
+ elif self.metric == "manhattan":
526
+ D_ij = (X_i - X_j).abs().sum(-1)
527
+ elif self.metric == "angular":
528
+ D_ij = -(X_i | X_j)
529
+ elif self.metric == "hyperbolic":
530
+ D_ij = ((X_i - X_j) ** 2).sum(-1) / (X_i[0] * X_j[0])
531
+ else:
532
+ raise NotImplementedError(f"The '{self.metric}' distance is not supported.")
533
+
534
+ self._x = x
535
+ self._KNN_fun = D_ij.Kmin(self.k, dim=1)
536
+ return self
537
+
538
+ def score_samples(self, x):
539
+ assert self._x is not None and self._KNN_fun is not None, "Fit first."
540
+ return self._KNN_fun(x, self._x).sum(axis=1) / self.k
541
+
542
+
500
543
  # def _pts_convolution_sparse(pts:np.ndarray, pts_weights:np.ndarray, filtration_grid:Iterable[np.ndarray], kernel="gaussian", bandwidth=0.1, **more_kde_args):
501
544
  # """
502
545
  # Old version of `convolution_signed_measures`. Scikitlearn's convolution is slower than the code above.
@@ -7,13 +7,13 @@ from numpy.typing import ArrayLike
7
7
  from scipy.spatial import KDTree
8
8
  from scipy.spatial.distance import cdist
9
9
 
10
- from multipers.ml.convolutions import DTM, available_kernels
10
+ from multipers.filtrations.density import DTM, available_kernels
11
11
  from multipers.simplex_tree_multi import SimplexTreeMulti, SimplexTreeMulti_type
12
12
 
13
13
  try:
14
14
  import pykeops
15
15
 
16
- from multipers.ml.convolutions import KDE
16
+ from multipers.filtrations.density import KDE
17
17
  except ImportError:
18
18
  from sklearn.neighbors import KernelDensity
19
19
  from warnings import warn
@@ -165,7 +165,7 @@ class Simplex_tree_multi_interface
165
165
 
166
166
  void compute_extended_filtration() { throw std::logic_error("Incompatible with multipers"); }
167
167
 
168
- Simplex_tree_multi_interface *collapse_edges(int nb_collapse_iteration) {
168
+ Simplex_tree_multi_interface *collapse_edges([[maybe_unused]] int nb_collapse_iteration) {
169
169
  throw std::logic_error("Incompatible with multipers");
170
170
  }
171
171
 
@@ -1039,7 +1039,8 @@ class One_critical_filtration : public std::vector<T> {
1039
1039
  std::lower_bound(filtration.begin(),
1040
1040
  filtration.end(),
1041
1041
  static_cast<typename oned_array::value_type>(Base::operator[](parameter))));
1042
- d = d == filtration.size() ? filtration.size() - 1 : d;
1042
+ int num_filtration_values = filtration.size();
1043
+ d = d == num_filtration_values ? std::max(num_filtration_values - 1,0) : d;
1043
1044
  Base::operator[](parameter) = coordinate ? static_cast<T>(d) : static_cast<T>(filtration[d]);
1044
1045
  }
1045
1046
  }
@@ -39,7 +39,7 @@ class Persistence_backend_h0 {
39
39
  using cycle_type = std::vector<unsigned int>;
40
40
  static const bool is_vine = true;
41
41
 
42
- std::vector<cycle_type> get_representative_cycles(bool update = true) const { throw "Unimplemented"; }
42
+ std::vector<cycle_type> get_representative_cycles([[maybe_unused]] bool update = true) const { throw "Unimplemented"; }
43
43
 
44
44
  class Barcode_iterator : public boost::iterator_facade<Barcode_iterator, const Bar &, boost::forward_traversal_tag> {
45
45
  public:
@@ -60,6 +60,13 @@ struct No_vine_multi_persistence_options : Gudhi::persistence_matrix::Default_op
60
60
  static const bool has_vine_update = false;
61
61
  };
62
62
 
63
+ template <Gudhi::persistence_matrix::Column_types column_type = Gudhi::persistence_matrix::Column_types::INTRUSIVE_SET>
64
+ struct fix_presentation_options : Gudhi::persistence_matrix::Default_options<column_type, true> {
65
+ using Index = std::uint32_t;
66
+ static const bool has_map_column_container = true;
67
+ static const bool has_removable_columns = true; // WARN : idx will change if map is not true
68
+ };
69
+
63
70
  template <class Matrix_options, class Boundary_matrix_type>
64
71
  class Persistence_backend_matrix {
65
72
  public:
@@ -228,7 +235,7 @@ class Persistence_backend_matrix {
228
235
 
229
236
  inline Barcode get_barcode() { return Barcode(matrix_, permutation_); }
230
237
 
231
- inline std::size_t size() { return this->matrix_.get_number_of_columns(); }
238
+ inline std::size_t size() const { return this->matrix_.get_number_of_columns(); }
232
239
 
233
240
  inline friend std::ostream &operator<<(std::ostream &stream, Persistence_backend_matrix &structure) {
234
241
  stream << "[\n";
@@ -314,7 +314,7 @@ class Naive_merge_forest {
314
314
  struct Barcode {
315
315
  Barcode() {}
316
316
 
317
- Barcode(int numberOfSimplices, int numberOfVertices)
317
+ Barcode(int numberOfSimplices, [[maybe_unused]] int numberOfVertices)
318
318
  : barcode_(numberOfSimplices), positionToBar_(numberOfSimplices), nextBarIndex_(0) {}
319
319
 
320
320
  friend void swap(Barcode &mf1, Barcode &mf2) {
@@ -6,6 +6,7 @@
6
6
  #include <algorithm>
7
7
  #include <boost/mpl/aux_/na_fwd.hpp>
8
8
  #include <cassert>
9
+ #include <csignal>
9
10
  #include <cstddef>
10
11
  #include <cstdint>
11
12
  // #include <gudhi/Simplex_tree/multi_filtrations/Finitely_critical_filtrations.h>
@@ -116,6 +117,19 @@ class PresentationStructure {
116
117
  return idx;
117
118
  }
118
119
 
120
+ PresentationStructure permute(const std::vector<index_type> &order) const {
121
+ std::vector<std::vector<index_type>> new_generators(generators.size());
122
+ std::vector<int> new_generator_dimensions(generator_dimensions.size());
123
+ for (std::size_t i = 0; i < order.size(); i++) {
124
+ new_generators[i] = std::vector<index_type>(generators[order[i]].size());
125
+ for (std::size_t j = 0; j < generators[order[i]].size(); j++) {
126
+ new_generators[i][j] = order[generators[order[i]][j]];
127
+ }
128
+ new_generator_dimensions[i] = generator_dimensions[order[i]];
129
+ }
130
+ return PresentationStructure(new_generators, new_generator_dimensions);
131
+ }
132
+
119
133
  private:
120
134
  std::vector<std::vector<index_type>> generators;
121
135
  std::vector<int> generator_dimensions;
@@ -184,7 +198,7 @@ class SimplicialStructure {
184
198
 
185
199
  inline unsigned int max_dimension() const { return max_dimension_; }
186
200
 
187
- int prune_above_dimension(int dim) { throw; }
201
+ int prune_above_dimension([[maybe_unused]] int dim) { throw "Not implemented"; }
188
202
 
189
203
  private:
190
204
  std::vector<std::vector<index_type>> boundaries;
@@ -238,18 +252,67 @@ class Truc {
238
252
  std::iota(generator_order.begin(), generator_order.end(), 0); // range
239
253
  }
240
254
 
241
- Truc() {};
242
-
243
- Truc &operator=(const Truc &other) {
244
- generator_filtration_values = other.generator_filtration_values;
245
- generator_order = other.generator_order;
246
- structure = other.structure;
247
- persistence = other.persistence;
248
- filtration_container = other.filtration_container;
255
+ Truc(const Truc &other)
256
+ : generator_filtration_values(other.generator_filtration_values),
257
+ generator_order(other.generator_order),
258
+ structure(other.structure),
259
+ filtration_container(other.filtration_container),
260
+ persistence(other.persistence) {
249
261
  persistence._update_permutation_ptr(generator_order);
262
+ }
263
+
264
+ Truc &operator=(Truc other) {
265
+ if (this != &other) {
266
+ generator_filtration_values = other.generator_filtration_values;
267
+ generator_order = other.generator_order;
268
+ structure = other.structure;
269
+ filtration_container = other.filtration_container;
270
+ persistence = other.persistence;
271
+ persistence._update_permutation_ptr(generator_order);
272
+ }
250
273
  return *this;
274
+ }
275
+
276
+ Truc() {};
277
+
278
+ inline bool dimension_order(const index_type &i, const index_type &j) const {
279
+ return structure.dimension(i) < structure.dimension(j);
280
+ };
281
+
282
+ inline bool colexical_order(const index_type &i, const index_type &j) const {
283
+ if (structure.dimension(i) > structure.dimension(j)) return false;
284
+ if (structure.dimension(i) < structure.dimension(j)) return true;
285
+ if constexpr (MultiFiltration::is_multicritical()) // TODO : this may not be the best
286
+ throw "Not implemented in the multicritical case";
287
+
288
+ for (int idx = generator_filtration_values[i].num_parameters() - 1; idx >= 0; --idx) {
289
+ if (generator_filtration_values[i][idx] < generator_filtration_values[j][idx])
290
+ return true;
291
+ else if (generator_filtration_values[i][idx] > generator_filtration_values[j][idx])
292
+ return false;
293
+ }
294
+ return false;
251
295
  };
252
296
 
297
+
298
+ template <class Fun>
299
+ inline Truc rearange_sort(const Fun&& fun) const {
300
+ std::vector<index_type> permutation(generator_order.size());
301
+ std::iota(permutation.begin(), permutation.end(), 0);
302
+ std::sort(permutation.begin(), permutation.end(), [&](std::size_t i, std::size_t j) {
303
+ return fun(i, j);
304
+ });
305
+ std::vector<MultiFiltration> new_filtration(generator_filtration_values.size());
306
+ for (std::size_t i = 0; i < generator_filtration_values.size(); i++) {
307
+ new_filtration[i] = generator_filtration_values[permutation[i]];
308
+ }
309
+ return Truc(structure.permute(permutation), new_filtration);
310
+ }
311
+
312
+ Truc colexical_rearange() const {
313
+ return rearange_sort([this](std::size_t i, std::size_t j) { return this->colexical_order(i, j); });
314
+ }
315
+
253
316
  template <bool ignore_inf>
254
317
  std::vector<std::pair<int, std::vector<index_type>>> get_current_boundary_matrix() {
255
318
  std::vector<index_type> permutation(generator_order.size());
@@ -375,7 +438,7 @@ class Truc {
375
438
  return PersBackend(structure, out_gen_order);
376
439
  }
377
440
 
378
- inline const bool has_persistence() { return this->persistence.size(); };
441
+ inline bool has_persistence() const { return this->persistence.size(); };
379
442
 
380
443
  inline void compute_persistence(const bool ignore_inf = true) {
381
444
  this->persistence = this->compute_persistence_out(
@@ -718,7 +781,7 @@ class Truc {
718
781
 
719
782
  inline TrucThread weak_copy() const { return TrucThread(*truc_ptr); }
720
783
 
721
- inline const bool has_persistence() { return this->persistence.size(); };
784
+ inline bool has_persistence() const { return this->persistence.size(); };
722
785
 
723
786
  inline const PersBackend &get_persistence() const { return persistence; }
724
787
 
@@ -827,19 +890,23 @@ class Truc {
827
890
 
828
891
  // FOR Python interface, but I'm not fan. Todo: do the lambda function in
829
892
  // cython?
830
- inline std::vector<split_barcode> persistence_on_lines(const std::vector<std::vector<value_type>> &basepoints) {
893
+ inline std::vector<split_barcode> persistence_on_lines(const std::vector<std::vector<value_type>> &basepoints,
894
+ bool ignore_inf) {
831
895
  return barcodes(
832
896
  [](const std::vector<value_type> &basepoint) { return Gudhi::multi_persistence::Line<value_type>(basepoint); },
833
- basepoints);
897
+ basepoints,
898
+ ignore_inf);
834
899
  }
835
900
 
836
901
  inline std::vector<split_barcode> persistence_on_lines(
837
- const std::vector<std::pair<std::vector<value_type>, std::vector<value_type>>> &bp_dirs) {
902
+ const std::vector<std::pair<std::vector<value_type>, std::vector<value_type>>> &bp_dirs,
903
+ bool ignore_inf) {
838
904
  return barcodes(
839
905
  [](const std::pair<std::vector<value_type>, std::vector<value_type>> &bpdir) {
840
906
  return Gudhi::multi_persistence::Line<value_type>(bpdir.first, bpdir.second);
841
907
  },
842
- bp_dirs);
908
+ bp_dirs,
909
+ ignore_inf);
843
910
  }
844
911
 
845
912
  void build_from_scc_file(const std::string &inFilePath,
@@ -15,7 +15,7 @@ cimport cython
15
15
  # from multipers.filtration_conversions cimport *
16
16
  # from multipers.mma_structures cimport boundary_matrix,float,pair,vector,intptr_t
17
17
  # cimport numpy as cnp
18
-
18
+ current_doc_url = "https://davidlapous.github.io/multipers/"
19
19
  doc_soft_urls = {
20
20
  "mpfree":"https://bitbucket.org/mkerber/mpfree/",
21
21
  "multi_chunk":"",
@@ -27,6 +27,8 @@ doc_soft_easy_install = {
27
27
  ```sh
28
28
  git clone {doc_soft_urls["mpfree"]}
29
29
  cd mpfree
30
+ cmake . --fresh
31
+ make
30
32
  sudo cp mpfree /usr/bin/
31
33
  cd ..
32
34
  rm -rf mpfree
@@ -36,6 +38,8 @@ rm -rf mpfree
36
38
  ```sh
37
39
  git clone {doc_soft_urls["multi_chunk"]}
38
40
  cd multi_chunk
41
+ cmake . --fresh
42
+ make
39
43
  sudo cp multi_chunk /usr/bin/
40
44
  cd ..
41
45
  rm -rf multi_chunk
@@ -45,6 +49,8 @@ rm -rf multi_chunk
45
49
  ```sh
46
50
  git clone {doc_soft_urls["function_delaunay"]}
47
51
  cd function_delaunay
52
+ cmake . --fresh
53
+ make
48
54
  sudo cp main /usr/bin/function_delaunay
49
55
  cd ..
50
56
  rm -rf function_delaunay
@@ -65,7 +71,6 @@ doc_soft_easy_install = defaultdict(lambda:"<Unknown>", doc_soft_easy_install)
65
71
 
66
72
  available_reduce_softs = Literal["mpfree","multi_chunk","2pac"]
67
73
 
68
-
69
74
  def _path_init(soft:str|os.PathLike):
70
75
  a = which(f"./{soft}")
71
76
  b = which(f"{soft}")
@@ -222,12 +227,14 @@ def _init_external_softwares(requires=[]):
222
227
  if pathes[soft] is None:
223
228
  global doc_soft_urls
224
229
  raise ValueError(f"""
225
- Did not found {soft}.
230
+ Did not find {soft}.
226
231
  Install it from {doc_soft_urls[soft]}, and put it in your current directory,
227
232
  or in you $PATH.
233
+ Documentation is available here: {current_doc_url}compilation.html#external-libraries
228
234
  For instance:
229
235
  {doc_soft_easy_install[soft]}
230
236
  """)
237
+ _init_external_softwares()
231
238
  def _check_available(soft:str):
232
239
  _init_external_softwares()
233
240
  return pathes.get(soft,None) is not None
@@ -255,8 +262,7 @@ def scc_reduce_from_str(
255
262
  backend: "mpfree", "multi_chunk" or "2pac"
256
263
  """
257
264
  global pathes, input_path, output_path
258
- if pathes[backend] is None:
259
- _init_external_softwares(requires=[backend])
265
+ assert _check_available(backend), f"Backend {backend} is not available."
260
266
 
261
267
 
262
268
  resolution_str = "--resolution" if full_resolution else ""
@@ -323,8 +329,7 @@ def scc_reduce_from_str_to_slicer(
323
329
  backend: "mpfree", "multi_chunk" or "2pac"
324
330
  """
325
331
  global pathes, input_path, output_path
326
- if pathes[backend] is None:
327
- _init_external_softwares(requires=[backend])
332
+ assert _check_available(backend), f"Backend {backend} is not available."
328
333
 
329
334
 
330
335
  resolution_str = "--resolution" if full_resolution else ""
@@ -443,8 +448,7 @@ def function_delaunay_presentation(
443
448
  id = str(threading.get_native_id())
444
449
  global input_path, output_path, pathes
445
450
  backend = "function_delaunay"
446
- if pathes[backend] is None :
447
- _init_external_softwares(requires=[backend])
451
+ assert _check_available(backend), f"Backend {backend} is not available."
448
452
 
449
453
  to_write = np.concatenate([point_cloud, function_values.reshape(-1,1)], axis=1)
450
454
  np.savetxt(input_path+id,to_write,delimiter=' ')
@@ -492,8 +496,7 @@ def function_delaunay_presentation_to_slicer(
492
496
  id = str(threading.get_native_id())
493
497
  global input_path, output_path, pathes
494
498
  backend = "function_delaunay"
495
- if pathes[backend] is None :
496
- _init_external_softwares(requires=[backend])
499
+ assert _check_available(backend), f"Backend {backend} is not available."
497
500
 
498
501
  to_write = np.concatenate([point_cloud, function_values.reshape(-1,1)], axis=1)
499
502
  np.savetxt(input_path+id,to_write,delimiter=' ')
@@ -10,7 +10,7 @@ from tqdm import tqdm
10
10
 
11
11
  import multipers as mp
12
12
  import multipers.slicer as mps
13
- from multipers.ml.convolutions import DTM, KDE, available_kernels
13
+ from multipers.filtrations.density import DTM, KDE, available_kernels
14
14
 
15
15
 
16
16
  class PointCloud2FilteredComplex(BaseEstimator, TransformerMixin):
@@ -176,7 +176,7 @@ class PointCloud2FilteredComplex(BaseEstimator, TransformerMixin):
176
176
  st = alpha_complex.create_simplex_tree(max_alpha_square=self._threshold**2)
177
177
  vertices = np.array([i for (i,), _ in st.get_skeleton(0)])
178
178
  new_points = np.asarray(
179
- [alpha_complex.get_point(i) for i in vertices]
179
+ [alpha_complex.get_point(int(i)) for i in vertices]
180
180
  ) # Seems to be unsafe for some reason
181
181
  # new_points = x
182
182
  st = mp.simplex_tree_multi.SimplexTreeMulti(
@@ -1,4 +1,4 @@
1
- from collections.abc import Callable, Iterable, Sequence
1
+ from collections.abc import Iterable, Sequence
2
2
  from itertools import product
3
3
  from typing import Optional, Union
4
4
 
@@ -10,8 +10,8 @@ from tqdm import tqdm
10
10
 
11
11
  import multipers as mp
12
12
  from multipers.grids import compute_grid as reduce_grid
13
- from multipers.ml.convolutions import available_kernels, convolution_signed_measures
14
- from multipers.point_measure import signed_betti, rank_decomposition_by_rectangles
13
+ from multipers.filtrations.density import available_kernels, convolution_signed_measures
14
+ from multipers.point_measure import rank_decomposition_by_rectangles, signed_betti
15
15
 
16
16
 
17
17
  class FilteredComplex2SignedMeasure(BaseEstimator, TransformerMixin):
@@ -580,7 +580,6 @@ cdef class PyModule_f64:
580
580
  cdef Box[double] c_box = Box[double](box)
581
581
  out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
582
582
  if plot:
583
- plt.figure()
584
583
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
585
584
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
586
585
  plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
@@ -614,7 +613,6 @@ cdef class PyModule_f64:
614
613
  out = np.array(self.cmod.get_landscapes(degree, ks, Box[double](box), resolution))
615
614
  if plot:
616
615
  to_plot = np.sum(out, axis=0)
617
- plt.figure()
618
616
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
619
617
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
620
618
  plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
@@ -1532,7 +1530,6 @@ cdef class PyModule_f32:
1532
1530
  cdef Box[float] c_box = Box[float](box)
1533
1531
  out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
1534
1532
  if plot:
1535
- plt.figure()
1536
1533
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
1537
1534
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
1538
1535
  plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
@@ -1566,7 +1563,6 @@ cdef class PyModule_f32:
1566
1563
  out = np.array(self.cmod.get_landscapes(degree, ks, Box[float](box), resolution))
1567
1564
  if plot:
1568
1565
  to_plot = np.sum(out, axis=0)
1569
- plt.figure()
1570
1566
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
1571
1567
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
1572
1568
  plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
@@ -602,7 +602,6 @@ cdef class PyModule_{{SHORT}}:
602
602
  cdef Box[{{CTYPE}}] c_box = Box[{{CTYPE}}](box)
603
603
  out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
604
604
  if plot:
605
- plt.figure()
606
605
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
607
606
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
608
607
  plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
@@ -636,7 +635,6 @@ cdef class PyModule_{{SHORT}}:
636
635
  out = np.array(self.cmod.get_landscapes(degree, ks, Box[{{CTYPE}}](box), resolution))
637
636
  if plot:
638
637
  to_plot = np.sum(out, axis=0)
639
- plt.figure()
640
638
  aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
641
639
  extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
642
640
  plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
@@ -2064,9 +2064,10 @@ inline void Summand<value_type>::complete_birth(const value_type precision) {
2064
2064
  for (std::size_t i = 0; i < birth_corners_.num_generators(); i++) {
2065
2065
  for (std::size_t j = i + 1; j < birth_corners_.num_generators(); j++) {
2066
2066
  value_type dinf = d_inf(birth_corners_[i], birth_corners_[j]);
2067
- if (dinf < 1.1 * precision) {
2067
+ if (dinf < .99 * precision) { // for machine error ?
2068
2068
  _factorize_min(birth_corners_[i], birth_corners_[j]);
2069
2069
  birth_corners_[j].clear();
2070
+ i++;
2070
2071
  }
2071
2072
  }
2072
2073
  }
@@ -2080,9 +2081,10 @@ inline void Summand<value_type>::complete_death(const value_type precision) {
2080
2081
  for (std::size_t i = 0; i < death_corners_.num_generators(); i++) {
2081
2082
  for (std::size_t j = i + 1; j < death_corners_.num_generators(); j++) {
2082
2083
  value_type d = d_inf(death_corners_[i], death_corners_[j]);
2083
- if (d < 1.1 * precision) {
2084
+ if (d < .99 * precision) {
2084
2085
  _factorize_max(death_corners_[i], death_corners_[j]);
2085
2086
  death_corners_[j].clear();
2087
+ i++;
2086
2088
  }
2087
2089
  }
2088
2090
  }
@@ -89,7 +89,7 @@ def module_approximation(
89
89
  input:Union[SimplexTreeMulti_type,Slicer_type, tuple],
90
90
  box:Optional[np.ndarray]=None,
91
91
  float max_error=-1,
92
- int nlines=500,
92
+ int nlines=557,
93
93
  slicer_backend:Literal["matrix","clement","graph"]="matrix",
94
94
  minpres:Optional[Literal["mpfree"]]=None,
95
95
  degree:Optional[int]=None,
@@ -166,6 +166,8 @@ def module_approximation(
166
166
  for i,m in enumerate(modules):
167
167
  mod.merge(m, input[i].minpres_degree)
168
168
  return mod
169
+ if len(input) == 0:
170
+ return PyModule_f64()
169
171
  if box is None:
170
172
  if is_simplextree_multi(input):
171
173
  box = input.filtration_bounds()
@@ -254,7 +254,7 @@ def plot2d_PyModule(
254
254
  dimension=-1,
255
255
  separated=False,
256
256
  min_persistence=0,
257
- alpha=1,
257
+ alpha=.8,
258
258
  verbose=False,
259
259
  save=False,
260
260
  dpi=200,