multipers 2.2.3__cp310-cp310-win_amd64.whl

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 (189) hide show
  1. multipers/__init__.py +31 -0
  2. multipers/_signed_measure_meta.py +430 -0
  3. multipers/_slicer_meta.py +212 -0
  4. multipers/data/MOL2.py +458 -0
  5. multipers/data/UCR.py +18 -0
  6. multipers/data/__init__.py +1 -0
  7. multipers/data/graphs.py +466 -0
  8. multipers/data/immuno_regions.py +27 -0
  9. multipers/data/minimal_presentation_to_st_bf.py +0 -0
  10. multipers/data/pytorch2simplextree.py +91 -0
  11. multipers/data/shape3d.py +101 -0
  12. multipers/data/synthetic.py +111 -0
  13. multipers/distances.py +198 -0
  14. multipers/filtration_conversions.pxd +229 -0
  15. multipers/filtration_conversions.pxd.tp +84 -0
  16. multipers/filtrations.pxd +224 -0
  17. multipers/function_rips.cp310-win_amd64.pyd +0 -0
  18. multipers/function_rips.pyx +105 -0
  19. multipers/grids.cp310-win_amd64.pyd +0 -0
  20. multipers/grids.pyx +350 -0
  21. multipers/gudhi/Persistence_slices_interface.h +132 -0
  22. multipers/gudhi/Simplex_tree_interface.h +245 -0
  23. multipers/gudhi/Simplex_tree_multi_interface.h +561 -0
  24. multipers/gudhi/cubical_to_boundary.h +59 -0
  25. multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
  26. multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
  27. multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
  28. multipers/gudhi/gudhi/Debug_utils.h +45 -0
  29. multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
  30. multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
  31. multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
  32. multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
  33. multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
  34. multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
  35. multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
  36. multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
  37. multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
  38. multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
  39. multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
  40. multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
  41. multipers/gudhi/gudhi/Matrix.h +2107 -0
  42. multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
  43. multipers/gudhi/gudhi/Multi_persistence/Box.h +171 -0
  44. multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
  45. multipers/gudhi/gudhi/Off_reader.h +173 -0
  46. multipers/gudhi/gudhi/One_critical_filtration.h +1431 -0
  47. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
  48. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
  49. multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
  50. multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
  51. multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
  52. multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
  53. multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
  54. multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
  55. multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
  56. multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
  57. multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
  58. multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
  59. multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
  60. multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
  61. multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
  62. multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
  63. multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
  64. multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
  65. multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
  66. multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
  67. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
  68. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
  69. multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
  70. multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
  71. multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
  72. multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
  73. multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
  74. multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
  75. multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
  76. multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
  77. multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
  78. multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
  79. multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
  80. multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
  81. multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
  82. multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
  83. multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
  84. multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
  85. multipers/gudhi/gudhi/Points_off_io.h +171 -0
  86. multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
  87. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
  88. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
  89. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
  90. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
  91. multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
  92. multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
  93. multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
  94. multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
  95. multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
  96. multipers/gudhi/gudhi/Simplex_tree_multi.h +163 -0
  97. multipers/gudhi/gudhi/distance_functions.h +62 -0
  98. multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
  99. multipers/gudhi/gudhi/persistence_interval.h +253 -0
  100. multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
  101. multipers/gudhi/gudhi/reader_utils.h +367 -0
  102. multipers/gudhi/mma_interface_coh.h +255 -0
  103. multipers/gudhi/mma_interface_h0.h +231 -0
  104. multipers/gudhi/mma_interface_matrix.h +282 -0
  105. multipers/gudhi/naive_merge_tree.h +575 -0
  106. multipers/gudhi/scc_io.h +289 -0
  107. multipers/gudhi/truc.h +888 -0
  108. multipers/io.cp310-win_amd64.pyd +0 -0
  109. multipers/io.pyx +711 -0
  110. multipers/ml/__init__.py +0 -0
  111. multipers/ml/accuracies.py +90 -0
  112. multipers/ml/convolutions.py +520 -0
  113. multipers/ml/invariants_with_persistable.py +79 -0
  114. multipers/ml/kernels.py +176 -0
  115. multipers/ml/mma.py +714 -0
  116. multipers/ml/one.py +472 -0
  117. multipers/ml/point_clouds.py +346 -0
  118. multipers/ml/signed_measures.py +1589 -0
  119. multipers/ml/sliced_wasserstein.py +461 -0
  120. multipers/ml/tools.py +113 -0
  121. multipers/mma_structures.cp310-win_amd64.pyd +0 -0
  122. multipers/mma_structures.pxd +127 -0
  123. multipers/mma_structures.pyx +2746 -0
  124. multipers/mma_structures.pyx.tp +1085 -0
  125. multipers/multi_parameter_rank_invariant/diff_helpers.h +93 -0
  126. multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
  127. multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
  128. multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
  129. multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
  130. multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
  131. multipers/multiparameter_edge_collapse.py +41 -0
  132. multipers/multiparameter_module_approximation/approximation.h +2295 -0
  133. multipers/multiparameter_module_approximation/combinatory.h +129 -0
  134. multipers/multiparameter_module_approximation/debug.h +107 -0
  135. multipers/multiparameter_module_approximation/euler_curves.h +0 -0
  136. multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
  137. multipers/multiparameter_module_approximation/heap_column.h +238 -0
  138. multipers/multiparameter_module_approximation/images.h +79 -0
  139. multipers/multiparameter_module_approximation/list_column.h +174 -0
  140. multipers/multiparameter_module_approximation/list_column_2.h +232 -0
  141. multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
  142. multipers/multiparameter_module_approximation/set_column.h +135 -0
  143. multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
  144. multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
  145. multipers/multiparameter_module_approximation/utilities.h +419 -0
  146. multipers/multiparameter_module_approximation/vector_column.h +223 -0
  147. multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
  148. multipers/multiparameter_module_approximation/vineyards.h +464 -0
  149. multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
  150. multipers/multiparameter_module_approximation.cp310-win_amd64.pyd +0 -0
  151. multipers/multiparameter_module_approximation.pyx +217 -0
  152. multipers/pickle.py +53 -0
  153. multipers/plots.py +334 -0
  154. multipers/point_measure.cp310-win_amd64.pyd +0 -0
  155. multipers/point_measure.pyx +320 -0
  156. multipers/simplex_tree_multi.cp310-win_amd64.pyd +0 -0
  157. multipers/simplex_tree_multi.pxd +133 -0
  158. multipers/simplex_tree_multi.pyx +10335 -0
  159. multipers/simplex_tree_multi.pyx.tp +1935 -0
  160. multipers/slicer.cp310-win_amd64.pyd +0 -0
  161. multipers/slicer.pxd +2371 -0
  162. multipers/slicer.pxd.tp +214 -0
  163. multipers/slicer.pyx +15467 -0
  164. multipers/slicer.pyx.tp +914 -0
  165. multipers/tbb12.dll +0 -0
  166. multipers/tbbbind_2_5.dll +0 -0
  167. multipers/tbbmalloc.dll +0 -0
  168. multipers/tbbmalloc_proxy.dll +0 -0
  169. multipers/tensor/tensor.h +672 -0
  170. multipers/tensor.pxd +13 -0
  171. multipers/test.pyx +44 -0
  172. multipers/tests/__init__.py +57 -0
  173. multipers/tests/test_diff_helper.py +73 -0
  174. multipers/tests/test_hilbert_function.py +82 -0
  175. multipers/tests/test_mma.py +83 -0
  176. multipers/tests/test_point_clouds.py +49 -0
  177. multipers/tests/test_python-cpp_conversion.py +82 -0
  178. multipers/tests/test_signed_betti.py +181 -0
  179. multipers/tests/test_signed_measure.py +89 -0
  180. multipers/tests/test_simplextreemulti.py +221 -0
  181. multipers/tests/test_slicer.py +221 -0
  182. multipers/torch/__init__.py +1 -0
  183. multipers/torch/diff_grids.py +217 -0
  184. multipers/torch/rips_density.py +304 -0
  185. multipers-2.2.3.dist-info/LICENSE +21 -0
  186. multipers-2.2.3.dist-info/METADATA +134 -0
  187. multipers-2.2.3.dist-info/RECORD +189 -0
  188. multipers-2.2.3.dist-info/WHEEL +5 -0
  189. multipers-2.2.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,89 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ import multipers as mp
5
+ import multipers.io as mio
6
+ from multipers.tests import assert_sm, random_st
7
+
8
+ np.random.seed(0)
9
+
10
+ st = random_st(npts=50).collapse_edges(-2, ignore_warning=True)
11
+
12
+ invariants = ["euler", "hilbert", "rank"]
13
+ degrees = [0, 1]
14
+ mass_defaults = [None, "auto"]
15
+ strats = [("regular_closest", 20), ("quantile", 20), ("regular", 17)]
16
+
17
+ mio._init_external_softwares()
18
+ mpfree_flag = mio._check_available("mpfree")
19
+
20
+
21
+ @pytest.mark.parametrize("invariant", invariants)
22
+ @pytest.mark.parametrize("degree", degrees)
23
+ @pytest.mark.parametrize("mass_default", mass_defaults)
24
+ @pytest.mark.parametrize("S", strats)
25
+ def test_backends(invariant, degree, mass_default, S):
26
+ degree = None if invariant == "euler" else degree
27
+ strat, r = S
28
+ sms = []
29
+ sms.append(
30
+ mp.signed_measure(
31
+ st,
32
+ degree=degree,
33
+ grid_strategy=strat,
34
+ resolution=r,
35
+ mass_default=mass_default,
36
+ invariant=invariant,
37
+ )[0]
38
+ )
39
+ sms.append(
40
+ mp.signed_measure(
41
+ st.grid_squeeze(grid_strategy=strat, resolution=r),
42
+ degree=degree,
43
+ mass_default=mass_default,
44
+ invariant=invariant,
45
+ )[0]
46
+ )
47
+ snv = mp.Slicer(st, vineyard=False)
48
+ sv = mp.Slicer(st, vineyard=True)
49
+ for s in [sv, snv]:
50
+ sms.append(
51
+ mp.signed_measure(
52
+ s,
53
+ degree=1,
54
+ grid_strategy=strat,
55
+ resolution=r,
56
+ mass_default=mass_default,
57
+ invariant=invariant,
58
+ )[0]
59
+ )
60
+ if invariant != "euler":
61
+ if not mpfree_flag:
62
+ pytest.skip(r"Skipping next test, as `mpfree` was not found.")
63
+ else:
64
+ for s in [sv, snv]:
65
+ assert s.minpres(degree=degree).is_minpres, "minpres is not minpres"
66
+ sms.append(
67
+ mp.signed_measure(
68
+ s.minpres(degree=degree),
69
+ degree=degree,
70
+ grid_strategy=strat,
71
+ resolution=r,
72
+ mass_default=mass_default,
73
+ invariant=invariant,
74
+ )[0]
75
+ )
76
+ sms.append(
77
+ mp.signed_measure(
78
+ st,
79
+ grid_strategy=strat,
80
+ degree=degree,
81
+ resolution=r,
82
+ mass_default=mass_default,
83
+ backend="mpfree",
84
+ invariant=invariant,
85
+ )[0]
86
+ )
87
+ if mass_default is not None and invariant != "rank":
88
+ assert sms[0][1].sum() == 0, "Did not remove all of the mass"
89
+ assert_sm(*sms, exact=False, max_error=0.5)
@@ -0,0 +1,221 @@
1
+ import pickle as pkl
2
+
3
+ import gudhi as gd
4
+ import numpy as np
5
+ from numpy import array
6
+
7
+ import multipers as mp
8
+ import pytest
9
+ from multipers.tests import assert_st_simplices, random_st
10
+
11
+
12
+
13
+ def test_1():
14
+ st = mp.SimplexTreeMulti(num_parameters=2)
15
+ st.insert([0], [0, 1])
16
+ st.insert([1], [1, 0])
17
+ st.insert([0, 1], [1, 1])
18
+ it = [([0, 1], [1.0, 1.0]), ([0], [0.0, 1.0]), ([1], [1.0, 0.0])]
19
+ assert_st_simplices(st, it)
20
+
21
+
22
+ def test_2():
23
+ from gudhi.rips_complex import RipsComplex
24
+
25
+ st2 = RipsComplex(points=[[0, 1], [1, 0], [0, 0]]).create_simplex_tree()
26
+ st2 = mp.SimplexTreeMulti(
27
+ st2, num_parameters=3, default_values=[1, 2]
28
+ ) # the gudhi filtration is placed on axis 0
29
+
30
+ it = (
31
+ ([0, 1], [np.sqrt(2), 1.0, 2.0]),
32
+ ([0, 2], [1.0, 1.0, 2.0]),
33
+ ([0], [0.0, 1.0, 2.0]),
34
+ ([1, 2], [1.0, 1.0, 2.0]),
35
+ ([1], [0.0, 1.0, 2.0]),
36
+ ([2], [0.0, 1.0, 2.0]),
37
+ )
38
+ assert_st_simplices(st2, it)
39
+
40
+
41
+ def test_3():
42
+ st = gd.SimplexTree() # usual gudhi simplextree
43
+ st.insert([0, 1], 1)
44
+ st.insert([1], 0)
45
+ # converts the simplextree into a multiparameter simplextree
46
+ for dtype in [np.int32, np.int64, np.float32, np.float64]:
47
+ try:
48
+ st_multi = mp.SimplexTreeMulti(st, num_parameters=4, dtype=dtype)
49
+ except KeyError:
50
+ import sys
51
+
52
+ print(f"type {dtype} not compiled, skipping.", file=sys.stderr)
53
+ continue ## dtype not compiled
54
+ minf = -np.inf if isinstance(dtype(1), np.floating) else np.iinfo(dtype).min
55
+ it = [
56
+ (array([0, 1]), array([1.0, minf, minf, minf])),
57
+ (array([0]), array([1.0, minf, minf, minf])),
58
+ (array([1]), array([0.0, minf, minf, minf])),
59
+ ]
60
+ assert_st_simplices(st_multi, it)
61
+
62
+
63
+ has_kcritical = np.any([a().is_kcritical for a in mp.simplex_tree_multi.available_simplextrees])
64
+ @pytest.mark.skipif(
65
+ not has_kcritical,
66
+ reason="kcritical simplextree not compiled, skipping this test",
67
+ )
68
+ def test_4():
69
+ st = mp.SimplexTreeMulti(num_parameters=2, kcritical=True, dtype=np.float64)
70
+ st.insert([0, 1, 2], [0, 1])
71
+ st.insert([0, 1, 2], [1, 0])
72
+ st.remove_maximal_simplex([0, 1, 2])
73
+ st.insert([0, 1, 2], [1, 2])
74
+ st.insert([0, 1, 2], [2, 1])
75
+ st.insert([0, 1, 2], [1.5, 1.5])
76
+ st.insert([0, 1, 2], [2.5, 0.5])
77
+ st.insert([0, 1, 2], [0.5, 2.5])
78
+
79
+ s = mp.Slicer(st, vineyard=True)
80
+
81
+ assert np.array_equal(
82
+ s.get_filtrations_values(),
83
+ array(
84
+ [
85
+ [0.0, 1.0],
86
+ [1.0, 0.0],
87
+ [0.0, 1.0],
88
+ [1.0, 0.0],
89
+ [0.0, 1.0],
90
+ [1.0, 0.0],
91
+ [0.0, 1.0],
92
+ [1.0, 0.0],
93
+ [0.0, 1.0],
94
+ [1.0, 0.0],
95
+ [0.0, 1.0],
96
+ [1.0, 0.0],
97
+ [0.5, 2.5],
98
+ [1.0, 2.0],
99
+ [1.5, 1.5],
100
+ [2.0, 1.0],
101
+ [2.5, 0.5],
102
+ ]
103
+ ),
104
+ ), "Invalid conversion from kcritical st to kcritical slicer."
105
+ death_curve = np.asarray(
106
+ mp.module_approximation(s, box=[[0, 0], [3, 3]])
107
+ .get_module_of_degree(1)[0]
108
+ .get_death_list()
109
+ )
110
+ assert np.array_equal(
111
+ death_curve,
112
+ array(
113
+ [
114
+ [0.5, np.inf],
115
+ [1.0, 2.5],
116
+ [1.5, 2.0],
117
+ [2.0, 1.5],
118
+ [2.5, 1.0],
119
+ [np.inf, 0.5],
120
+ ]
121
+ ),
122
+ )
123
+
124
+
125
+ def test_make_filtration_non_decreasing():
126
+ st = mp.SimplexTreeMulti(num_parameters=2)
127
+ st.insert([0], [1, 2])
128
+ st.insert([1], [2, 3])
129
+ st.insert([2], [3, 2])
130
+
131
+ st.insert([0, 1], [10, 21])
132
+ st.insert([2, 0], [11, 20])
133
+
134
+ st.insert([0, 1, 2], [-np.inf, -np.inf])
135
+ assert (st.filtration([1, 2]) == 3).all()
136
+ assert (st.filtration([0, 1, 2]) == [11, 21]).all()
137
+ st.make_filtration_non_decreasing()
138
+ assert (st.filtration([1, 2]) == 3).all()
139
+ assert (st.filtration([0, 1, 2]) == [11, 21]).all()
140
+
141
+
142
+ def test_flagify():
143
+ st = mp.SimplexTreeMulti(num_parameters=2)
144
+
145
+ st.insert([0], [1, 4])
146
+ st.insert([1], [2, 3])
147
+ st.insert([2], [3, 2])
148
+
149
+ st.insert([0, 1], [21, 20])
150
+ st.insert([2, 0], [20, 21])
151
+ st.insert([1, 2])
152
+ st.insert([0, 1, 2], [41, 55])
153
+
154
+ st.flagify(2)
155
+ assert (st.filtration([0, 1, 2]) == 21).all()
156
+ st.flagify(1)
157
+ assert (np.array([f for s, f in st]).max(axis=0) == [3, 4]).all()
158
+ st.flagify(0)
159
+ assert (np.array([f for s, f in st]) == -np.inf).all()
160
+
161
+
162
+ def test_distance_matrix_filling():
163
+ X = np.random.uniform(size=(200, 2))
164
+ D = np.sqrt(((X[None] - X[:, None]) ** 2).sum(axis=-1))
165
+ st = gd.RipsComplex(distance_matrix=D).create_simplex_tree()
166
+ st = mp.SimplexTreeMulti(st, num_parameters=1)
167
+ st2 = mp.SimplexTreeMulti(st)
168
+ assert st2.num_parameters == 1
169
+ st2.fill_lowerstar(np.zeros(st.num_vertices), 0)
170
+ assert st2 != st
171
+ st2.fill_distance_matrix(D, 0)
172
+ assert st2 == st
173
+
174
+
175
+ def test_serialize():
176
+ stm = random_st(num_parameters=4)
177
+ stm2 = pkl.loads(pkl.dumps(stm))
178
+ assert stm == stm2
179
+ stm2[[0]][:] = stm2[[0]] + 1
180
+ assert not stm == stm2
181
+ st1 = stm.project_on_line(parameter=0)
182
+ stm = mp.SimplexTreeMulti(st1, num_parameters=3)
183
+ assert st1 == stm.project_on_line(
184
+ parameter=0
185
+ ), "Gudhi<->Multipers conversion failed"
186
+
187
+
188
+ @pytest.mark.skipif(
189
+ not has_kcritical,
190
+ reason="kcritical simplextree not compiled, skipping this test",
191
+ )
192
+ def test_kcritical_batch_insert():
193
+
194
+ st = mp.SimplexTreeMulti(num_parameters=2, kcritical=True, dtype=np.float64)
195
+
196
+ vertices = [[0,1]]
197
+ vertices_filtrations = np.array([[[-1, -2]],[[-2, -1]]])
198
+ st.insert_batch(vertices,vertices_filtrations)
199
+
200
+ edges = np.array([[0, 1],[1, 2], [2,0]]).T
201
+ edges_filtrations = np.array([
202
+ [[1,0],[0,1], [np.inf,np.inf]],
203
+ [[1,0],[0,1], [np.inf,np.inf]],
204
+ [[1,0],[0,1], [-1,3]],
205
+ ])
206
+ st.insert_batch(edges, edges_filtrations)
207
+
208
+ triangle = np.array([[0,1,2]]).T
209
+ triangle_filration = [[[2,2]]]
210
+ st.insert_batch(triangle, triangle_filration)
211
+
212
+ from numpy import array
213
+ goal = [(array([0, 1, 2]), [array([2., 2.])]),
214
+ (array([0, 1]), [array([0., 1.]), array([1., 0.])]),
215
+ (array([0, 2]), [array([-1., 3.]), array([0., 1.]), array([1., 0.])]),
216
+ (array([0]), [array([-1., -2.])]),
217
+ (array([1, 2]), [array([0., 1.]), array([1., 0.])]),
218
+ (array([1]), [array([-2., -1.])]),
219
+ (array([2]), [array([0., 1.]), array([1., 0.])])
220
+ ]
221
+ assert_st_simplices(st, goal)
@@ -0,0 +1,221 @@
1
+ import numpy as np
2
+ import pytest
3
+ from numpy import array
4
+
5
+ import multipers as mp
6
+ import multipers.slicer as mps
7
+ from multipers.tests import assert_sm
8
+ import pickle as pkl
9
+
10
+ mpfree_flag = mp.io._check_available("mpfree")
11
+ fd_flag = mp.io._check_available("function_delaunay")
12
+
13
+
14
+ def test_1():
15
+ st = mp.SimplexTreeMulti(num_parameters=2)
16
+ st.insert([0], [0, 1])
17
+ st.insert([1], [1, 0])
18
+ st.insert([0, 1], [1, 1])
19
+ for S in mps.available_slicers:
20
+ if not S().is_vine or not S().col_type or S().is_kcritical:
21
+ continue
22
+ from multipers._slicer_meta import _blocks2boundary_dimension_grades
23
+
24
+ generator_maps, generator_dimensions, filtration_values = (
25
+ _blocks2boundary_dimension_grades(
26
+ st._to_scc(),
27
+ inplace=False,
28
+ )
29
+ )
30
+ it = S(
31
+ generator_maps, generator_dimensions, filtration_values
32
+ ).persistence_on_line([0, 0])
33
+ assert (
34
+ len(it) == 2
35
+ ), "There are simplices of dim 0 and 1, but no pers ? got {}".format(len(it))
36
+ assert len(it[1]) == 0, "Pers of dim 1 is not empty ? got {}".format(it[1])
37
+ for x in it[0]:
38
+ if np.any(np.asarray(x)):
39
+ continue
40
+ assert x[0] == 1 and x[1] > 45, "pers should be [1,inf], got {}".format(x)
41
+
42
+
43
+ def test_2():
44
+ st = mp.SimplexTreeMulti(num_parameters=2)
45
+ st.insert([0], [0, 1])
46
+ st.insert([1], [1, 0])
47
+ st.insert([0, 1], [1, 1])
48
+ st.insert([0, 1, 2], [2, 2])
49
+ assert mp.slicer.to_simplextree(mp.Slicer(st, dtype=st.dtype)) == st
50
+
51
+
52
+ def test_3():
53
+ st = mp.SimplexTreeMulti(num_parameters=2)
54
+ st.insert([0], [0, 1])
55
+ st.insert([1], [1, 0])
56
+ st.insert([0, 1], [1, 1])
57
+ sm = mp.signed_measure(st, invariant="rank", degree=0)
58
+ sm2 = mp.signed_measure(mp.Slicer(st, dtype=np.int32), invariant="rank", degree=0)
59
+ sm3 = mp.signed_measure(mp.Slicer(st, dtype=np.float64), invariant="rank", degree=0)
60
+ it = [
61
+ (
62
+ array([[0.0, 1.0, 1.0, 1.0], [1.0, 0.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0]]),
63
+ array([1, 1, -1]),
64
+ )
65
+ ]
66
+ assert_sm(sm, it)
67
+ assert_sm(sm2, it)
68
+ assert_sm(sm3, it)
69
+
70
+
71
+ def test_representative_cycles():
72
+ truc = [
73
+ {},
74
+ {},
75
+ {},
76
+ {},
77
+ {},
78
+ {},
79
+ {},
80
+ {2, 3},
81
+ {4, 5},
82
+ {0, 2},
83
+ {0, 1},
84
+ {1, 3},
85
+ {1, 2},
86
+ {7, 11, 12},
87
+ {9, 10, 12},
88
+ {5, 6},
89
+ {2, 4},
90
+ {4, 6},
91
+ {8, 15, 17},
92
+ {3, 6},
93
+ ]
94
+ truc = [list(machin) for machin in truc]
95
+ slicer = mp.slicer._Slicer_Matrix0_vine_f64(
96
+ truc,
97
+ np.array([max(len(x) - 1, 0) for x in truc]),
98
+ np.array([list(range(len(truc))), list(range(len(truc)))]).T,
99
+ )
100
+ slicer.compute_persistence(one_filtration=list(range(len(truc))))
101
+ cycles = slicer.get_representative_cycles()
102
+ assert len(cycles) == 3, f"There should be 3 dimensions here, found {len(cycles)}"
103
+ assert (
104
+ np.asarray(cycles[0]).shape[0] == 7
105
+ ), f"Invalid number of 0-cycles, got {np.asarray(cycles[0]).size}"
106
+ for c in cycles[1]:
107
+ assert (
108
+ np.unique(cycles[1][0], return_counts=True)[1] == 2
109
+ ).all(), f"Found a non-cycle, {cycles[1][0]}"
110
+ assert len(cycles[2]) == 0, "Found a 2-cycle, which should not exist"
111
+
112
+
113
+ def test_pruning():
114
+ from multipers.tests import random_st
115
+
116
+ st = random_st(num_parameters=3, max_dim=4)
117
+ s = mp.Slicer(st)
118
+ s.prune_above_dimension(2)
119
+ s2 = mp.Slicer(s, max_dim=2)
120
+ assert s.get_dimensions()[-1] == 2, "Failed to prune dimension"
121
+ st.prune_above_dimension(2)
122
+ assert (
123
+ s.get_dimensions() == s2.get_dimensions()
124
+ ).all(), "pruned dimensions do not coincide"
125
+ assert s.get_boundaries() == s2.get_boundaries(), "Boundaries changed"
126
+ assert (
127
+ s.get_filtrations_values() == s2.get_filtrations_values()
128
+ ).all(), "Filtrations have changed"
129
+
130
+
131
+ def test_scc():
132
+ import numpy as np
133
+
134
+ import multipers as mp
135
+ from multipers.distances import sm_distance
136
+ from multipers.io import _check_available
137
+ from multipers.tests import random_st
138
+
139
+ st = random_st(npts=500, num_parameters=2)
140
+ s = mp.Slicer(st, dtype=np.float64)
141
+ s.to_scc("truc.scc", degree=1)
142
+ s2 = mp.Slicer("truc.scc")
143
+ (a,) = mp.signed_measure(s)
144
+ (b,) = mp.signed_measure(s2)
145
+ assert sm_distance(a, b) < np.finfo(np.float64).resolution * s.num_generators
146
+
147
+ st = random_st(npts=500)
148
+ s = mp.Slicer(st).grid_squeeze(inplace=True)
149
+ s.filtration_grid = []
150
+ s.to_scc("truc.scc", degree=1)
151
+ s2 = mp.Slicer("truc.scc", dtype=np.float64)
152
+ (a,) = mp.signed_measure(s)
153
+ (b,) = mp.signed_measure(s2)
154
+ assert sm_distance(a, b) == 0
155
+
156
+ st = random_st(npts=200)
157
+ s = mp.Slicer(st).grid_squeeze(inplace=True)
158
+ s.filtration_grid = []
159
+ s.to_scc(
160
+ "truc.scc",
161
+ )
162
+ if _check_available("mpfree"):
163
+ s2 = mp.Slicer("truc.scc", dtype=np.float64).minpres(1)
164
+ (a,) = mp.signed_measure(s, degree=1)
165
+ (b,) = mp.signed_measure(s2, degree=1)
166
+ assert sm_distance(a, b) == 0
167
+ else:
168
+ pytest.skip("Skipped a test bc `mpfree` was not found.")
169
+
170
+
171
+ def test_bitmap():
172
+ img = np.random.uniform(size=(12, 10, 11, 2))
173
+ num_parameters = img.shape[-1]
174
+ s = mp.slicer.from_bitmap(img)
175
+ num_vertices = np.searchsorted(s.get_dimensions(), 1)
176
+ assert num_vertices == np.prod(img.shape[:-1])
177
+ assert s.num_parameters == num_parameters
178
+ assert s.dimension == img.ndim - 1
179
+ assert np.all(
180
+ np.asarray(s.get_filtrations()[:num_vertices])
181
+ == img.reshape(-1, num_parameters)
182
+ )
183
+
184
+
185
+ @pytest.mark.skipif(
186
+ not fd_flag or not mpfree_flag,
187
+ reason="Skipped external test as `function_delaunay`, `mpfree` were not found.",
188
+ )
189
+ @pytest.mark.parametrize("dim", [1, 2, 3, 4])
190
+ @pytest.mark.parametrize("degree", [1, 2, 3])
191
+ def test_external(dim, degree):
192
+ if degree >= dim:
193
+ return
194
+ X = np.random.uniform(size=(100, dim))
195
+ f = np.random.uniform(size=(X.shape[0]))
196
+ fd = mps.from_function_delaunay(X, f)
197
+ assert np.array_equal(np.unique(fd.get_dimensions()), np.arange(dim + 2))
198
+ fd_ = mps.from_function_delaunay(X, f, degree=degree)
199
+ assert np.array_equal(
200
+ np.unique(fd_.get_dimensions()), [degree, degree + 1]
201
+ ) ## only does presentations
202
+ fd_ = fd.minpres(degree=degree)
203
+ assert np.array_equal(
204
+ np.unique(fd_.get_dimensions()), [degree, degree + 1, degree + 2]
205
+ ) ## resolution by default
206
+
207
+ def test_pkl():
208
+ for num_params in range(1,4):
209
+ img = np.random.uniform(size=(20,20,num_params))
210
+ img2 = np.array(img)
211
+ img2[0,0,0]+=1
212
+ s = mp.slicer.from_bitmap(img)
213
+ s2 = mp.slicer.from_bitmap(img2)
214
+ s3 = type(s)(s.get_boundaries()[:-1], s.get_dimensions()[:-1], s.get_filtrations()[:-1])
215
+ s4 = type(s)(s.get_boundaries(), s.get_dimensions()+1, s.get_filtrations())
216
+ assert len(s)> np.prod(img.shape[:-1])+1
217
+ assert s == s.copy()
218
+ assert s != s2
219
+ assert s != s3
220
+ assert s != s4
221
+ assert s == pkl.loads(pkl.dumps(s))
@@ -0,0 +1 @@
1
+ from .rips_density import *