multipers 2.4.0b1__cp312-cp312-macosx_11_0_arm64.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.
Files changed (184) hide show
  1. multipers/.dylibs/libboost_timer.dylib +0 -0
  2. multipers/.dylibs/libc++.1.0.dylib +0 -0
  3. multipers/.dylibs/libtbb.12.17.dylib +0 -0
  4. multipers/__init__.py +33 -0
  5. multipers/_signed_measure_meta.py +426 -0
  6. multipers/_slicer_meta.py +231 -0
  7. multipers/array_api/__init__.py +62 -0
  8. multipers/array_api/numpy.py +124 -0
  9. multipers/array_api/torch.py +133 -0
  10. multipers/data/MOL2.py +458 -0
  11. multipers/data/UCR.py +18 -0
  12. multipers/data/__init__.py +1 -0
  13. multipers/data/graphs.py +466 -0
  14. multipers/data/immuno_regions.py +27 -0
  15. multipers/data/minimal_presentation_to_st_bf.py +0 -0
  16. multipers/data/pytorch2simplextree.py +91 -0
  17. multipers/data/shape3d.py +101 -0
  18. multipers/data/synthetic.py +113 -0
  19. multipers/distances.py +202 -0
  20. multipers/filtration_conversions.pxd +736 -0
  21. multipers/filtration_conversions.pxd.tp +226 -0
  22. multipers/filtrations/__init__.py +21 -0
  23. multipers/filtrations/density.py +529 -0
  24. multipers/filtrations/filtrations.py +480 -0
  25. multipers/filtrations.pxd +534 -0
  26. multipers/filtrations.pxd.tp +332 -0
  27. multipers/function_rips.cpython-312-darwin.so +0 -0
  28. multipers/function_rips.pyx +104 -0
  29. multipers/grids.cpython-312-darwin.so +0 -0
  30. multipers/grids.pyx +538 -0
  31. multipers/gudhi/Persistence_slices_interface.h +213 -0
  32. multipers/gudhi/Simplex_tree_interface.h +274 -0
  33. multipers/gudhi/Simplex_tree_multi_interface.h +648 -0
  34. multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
  35. multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
  36. multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
  37. multipers/gudhi/gudhi/Debug_utils.h +52 -0
  38. multipers/gudhi/gudhi/Degree_rips_bifiltration.h +2307 -0
  39. multipers/gudhi/gudhi/Dynamic_multi_parameter_filtration.h +2524 -0
  40. multipers/gudhi/gudhi/Fields/Multi_field.h +453 -0
  41. multipers/gudhi/gudhi/Fields/Multi_field_operators.h +460 -0
  42. multipers/gudhi/gudhi/Fields/Multi_field_shared.h +444 -0
  43. multipers/gudhi/gudhi/Fields/Multi_field_small.h +584 -0
  44. multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +490 -0
  45. multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +580 -0
  46. multipers/gudhi/gudhi/Fields/Z2_field.h +391 -0
  47. multipers/gudhi/gudhi/Fields/Z2_field_operators.h +389 -0
  48. multipers/gudhi/gudhi/Fields/Zp_field.h +493 -0
  49. multipers/gudhi/gudhi/Fields/Zp_field_operators.h +384 -0
  50. multipers/gudhi/gudhi/Fields/Zp_field_shared.h +492 -0
  51. multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
  52. multipers/gudhi/gudhi/Matrix.h +2200 -0
  53. multipers/gudhi/gudhi/Multi_filtration/Multi_parameter_generator.h +1712 -0
  54. multipers/gudhi/gudhi/Multi_filtration/multi_filtration_conversions.h +237 -0
  55. multipers/gudhi/gudhi/Multi_filtration/multi_filtration_utils.h +225 -0
  56. multipers/gudhi/gudhi/Multi_parameter_filtered_complex.h +485 -0
  57. multipers/gudhi/gudhi/Multi_parameter_filtration.h +2643 -0
  58. multipers/gudhi/gudhi/Multi_persistence/Box.h +233 -0
  59. multipers/gudhi/gudhi/Multi_persistence/Line.h +309 -0
  60. multipers/gudhi/gudhi/Multi_persistence/Multi_parameter_filtered_complex_pcoh_interface.h +268 -0
  61. multipers/gudhi/gudhi/Multi_persistence/Persistence_interface_cohomology.h +159 -0
  62. multipers/gudhi/gudhi/Multi_persistence/Persistence_interface_matrix.h +463 -0
  63. multipers/gudhi/gudhi/Multi_persistence/Point.h +853 -0
  64. multipers/gudhi/gudhi/Off_reader.h +173 -0
  65. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +834 -0
  66. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +838 -0
  67. multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +833 -0
  68. multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1367 -0
  69. multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1157 -0
  70. multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +869 -0
  71. multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +905 -0
  72. multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +122 -0
  73. multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +260 -0
  74. multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +288 -0
  75. multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +170 -0
  76. multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +247 -0
  77. multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +571 -0
  78. multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +182 -0
  79. multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +130 -0
  80. multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +235 -0
  81. multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +312 -0
  82. multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1092 -0
  83. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +923 -0
  84. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +914 -0
  85. multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +930 -0
  86. multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1071 -0
  87. multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +203 -0
  88. multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +886 -0
  89. multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +984 -0
  90. multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1213 -0
  91. multipers/gudhi/gudhi/Persistence_matrix/index_mapper.h +58 -0
  92. multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +227 -0
  93. multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +200 -0
  94. multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +166 -0
  95. multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +319 -0
  96. multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +562 -0
  97. multipers/gudhi/gudhi/Persistence_on_a_line.h +152 -0
  98. multipers/gudhi/gudhi/Persistence_on_rectangle.h +617 -0
  99. multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
  100. multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
  101. multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
  102. multipers/gudhi/gudhi/Persistent_cohomology.h +769 -0
  103. multipers/gudhi/gudhi/Points_off_io.h +171 -0
  104. multipers/gudhi/gudhi/Projective_cover_kernel.h +379 -0
  105. multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
  106. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +559 -0
  107. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
  108. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +121 -0
  109. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
  110. multipers/gudhi/gudhi/Simplex_tree/filtration_value_utils.h +155 -0
  111. multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
  112. multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
  113. multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +60 -0
  114. multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +105 -0
  115. multipers/gudhi/gudhi/Simplex_tree.h +3170 -0
  116. multipers/gudhi/gudhi/Slicer.h +848 -0
  117. multipers/gudhi/gudhi/Thread_safe_slicer.h +393 -0
  118. multipers/gudhi/gudhi/distance_functions.h +62 -0
  119. multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
  120. multipers/gudhi/gudhi/multi_simplex_tree_helpers.h +147 -0
  121. multipers/gudhi/gudhi/persistence_interval.h +263 -0
  122. multipers/gudhi/gudhi/persistence_matrix_options.h +188 -0
  123. multipers/gudhi/gudhi/reader_utils.h +367 -0
  124. multipers/gudhi/gudhi/simple_mdspan.h +484 -0
  125. multipers/gudhi/gudhi/slicer_helpers.h +779 -0
  126. multipers/gudhi/tmp_h0_pers/mma_interface_h0.h +223 -0
  127. multipers/gudhi/tmp_h0_pers/naive_merge_tree.h +536 -0
  128. multipers/io.cpython-312-darwin.so +0 -0
  129. multipers/io.pyx +472 -0
  130. multipers/ml/__init__.py +0 -0
  131. multipers/ml/accuracies.py +90 -0
  132. multipers/ml/invariants_with_persistable.py +79 -0
  133. multipers/ml/kernels.py +176 -0
  134. multipers/ml/mma.py +713 -0
  135. multipers/ml/one.py +472 -0
  136. multipers/ml/point_clouds.py +352 -0
  137. multipers/ml/signed_measures.py +1667 -0
  138. multipers/ml/sliced_wasserstein.py +461 -0
  139. multipers/ml/tools.py +113 -0
  140. multipers/mma_structures.cpython-312-darwin.so +0 -0
  141. multipers/mma_structures.pxd +134 -0
  142. multipers/mma_structures.pyx +1483 -0
  143. multipers/mma_structures.pyx.tp +1126 -0
  144. multipers/multi_parameter_rank_invariant/diff_helpers.h +85 -0
  145. multipers/multi_parameter_rank_invariant/euler_characteristic.h +95 -0
  146. multipers/multi_parameter_rank_invariant/function_rips.h +317 -0
  147. multipers/multi_parameter_rank_invariant/hilbert_function.h +761 -0
  148. multipers/multi_parameter_rank_invariant/persistence_slices.h +149 -0
  149. multipers/multi_parameter_rank_invariant/rank_invariant.h +350 -0
  150. multipers/multiparameter_edge_collapse.py +41 -0
  151. multipers/multiparameter_module_approximation/approximation.h +2541 -0
  152. multipers/multiparameter_module_approximation/debug.h +107 -0
  153. multipers/multiparameter_module_approximation/format_python-cpp.h +292 -0
  154. multipers/multiparameter_module_approximation/utilities.h +428 -0
  155. multipers/multiparameter_module_approximation.cpython-312-darwin.so +0 -0
  156. multipers/multiparameter_module_approximation.pyx +286 -0
  157. multipers/ops.cpython-312-darwin.so +0 -0
  158. multipers/ops.pyx +231 -0
  159. multipers/pickle.py +89 -0
  160. multipers/plots.py +550 -0
  161. multipers/point_measure.cpython-312-darwin.so +0 -0
  162. multipers/point_measure.pyx +409 -0
  163. multipers/simplex_tree_multi.cpython-312-darwin.so +0 -0
  164. multipers/simplex_tree_multi.pxd +136 -0
  165. multipers/simplex_tree_multi.pyx +11719 -0
  166. multipers/simplex_tree_multi.pyx.tp +2102 -0
  167. multipers/slicer.cpython-312-darwin.so +0 -0
  168. multipers/slicer.pxd +2097 -0
  169. multipers/slicer.pxd.tp +263 -0
  170. multipers/slicer.pyx +13042 -0
  171. multipers/slicer.pyx.tp +1259 -0
  172. multipers/tensor/tensor.h +672 -0
  173. multipers/tensor.pxd +13 -0
  174. multipers/test.pyx +44 -0
  175. multipers/tests/__init__.py +70 -0
  176. multipers/torch/__init__.py +1 -0
  177. multipers/torch/diff_grids.py +240 -0
  178. multipers/torch/rips_density.py +310 -0
  179. multipers/vector_interface.pxd +46 -0
  180. multipers-2.4.0b1.dist-info/METADATA +131 -0
  181. multipers-2.4.0b1.dist-info/RECORD +184 -0
  182. multipers-2.4.0b1.dist-info/WHEEL +6 -0
  183. multipers-2.4.0b1.dist-info/licenses/LICENSE +21 -0
  184. multipers-2.4.0b1.dist-info/top_level.txt +1 -0
multipers/io.pyx ADDED
@@ -0,0 +1,472 @@
1
+ import re
2
+ import tempfile
3
+ from gudhi import SimplexTree
4
+ import gudhi as gd
5
+ import numpy as np
6
+ import os
7
+ from shutil import which
8
+ from libcpp cimport bool
9
+ from typing import Optional, Literal
10
+ from collections import defaultdict
11
+ import itertools
12
+ import threading
13
+ import cython
14
+ cimport cython
15
+
16
+ current_doc_url = "https://davidlapous.github.io/multipers/"
17
+ doc_soft_urls = {
18
+ "mpfree":"https://bitbucket.org/mkerber/mpfree/",
19
+ "multi_chunk":"https://bitbucket.org/mkerber/multi_chunk/",
20
+ "function_delaunay":"https://bitbucket.org/mkerber/function_delaunay/",
21
+ "2pac":"https://gitlab.com/flenzen/2pac",
22
+ "rhomboid_tiling":"https://github.com/odinhg/rhomboidtiling_newer_cgal_version",
23
+ "multi_critical":"https://bitbucket.org/mkerber/multi_critical",
24
+ }
25
+ doc_soft_easy_install = {
26
+ "mpfree":f"""
27
+ ```sh
28
+ git clone {doc_soft_urls["mpfree"]}
29
+ cd mpfree
30
+ cmake . --fresh
31
+ make
32
+ cp mpfree $CONDA_PREFIX/bin/
33
+ cd ..
34
+ rm -rf mpfree
35
+ ```
36
+ """,
37
+ "multi_chunk":f"""
38
+ ```sh
39
+ git clone {doc_soft_urls["multi_chunk"]}
40
+ cd multi_chunk
41
+ cmake . --fresh
42
+ make
43
+ cp multi_chunk $CONDA_PREFIX/bin/
44
+ cd ..
45
+ rm -rf multi_chunk
46
+ ```
47
+ """,
48
+ "function_delaunay":f"""
49
+ ```sh
50
+ git clone {doc_soft_urls["function_delaunay"]}
51
+ cd function_delaunay
52
+ cmake . --fresh
53
+ make
54
+ cp main $CONDA_PREFIX/bin/function_delaunay
55
+ cd ..
56
+ rm -rf function_delaunay
57
+ ```
58
+ """,
59
+ "2pac":f"""
60
+ ```sh
61
+ git clone {doc_soft_urls["2pac"]} 2pac
62
+ cd 2pac && mkdir build && cd build
63
+ cmake ..
64
+ make
65
+ cp 2pac $CONDA_PREFIX/bin
66
+ ```
67
+ """,
68
+ "rhomboid_tiling":f"""
69
+ git clone {doc_soft_urls["rhomboid_tiling"]} rhomboid_tiling
70
+ cd rhomboid_tiling
71
+ sh build.sh
72
+ cp orderk $CONDA_PREFIX/bin/rhomboid_tiling
73
+ """,
74
+ "multi_critical":f"""
75
+ ```sh
76
+ git clone https://bitbucket.org/mkerber/multi_critical
77
+ cd multi_critical
78
+ cmake . --fresh
79
+ make
80
+ cp multi_critical $CONDA_PREFIX/bin/
81
+ cd ..
82
+ """,
83
+
84
+ }
85
+ doc_soft_urls = defaultdict(lambda:"<Unknown url>", doc_soft_urls)
86
+ doc_soft_easy_install = defaultdict(lambda:"<Unknown>", doc_soft_easy_install)
87
+
88
+ available_reduce_softs = Literal["mpfree","multi_chunk","2pac"]
89
+
90
+ def _path_init(soft:str|os.PathLike):
91
+ a = which(f"./{soft}")
92
+ b = which(f"{soft}")
93
+ if a:
94
+ pathes[soft] = a
95
+ elif b:
96
+ pathes[soft] = b
97
+
98
+ if pathes[soft] is not None:
99
+ verbose_arg = "> /dev/null 2>&1"
100
+ test = os.system(pathes[soft] + " --help " + verbose_arg)
101
+ if test % 256!=0:
102
+ from warnings import warn
103
+ warn(f"""
104
+ Found external software {soft} at {pathes[soft]}
105
+ but may not behave well.
106
+ """)
107
+
108
+
109
+
110
+ cdef dict[str,str|None] pathes = {
111
+ "mpfree":None,
112
+ "2pac":None,
113
+ "function_delaunay":None,
114
+ "multi_chunk":None,
115
+ "multi_critical":None,
116
+ "rhomboid_tiling":None
117
+ }
118
+
119
+
120
+
121
+ ## TODO : optimize with Python.h ?
122
+ def scc_parser(path: str| os.PathLike):
123
+ """
124
+ Parse an scc file into the scc python format, aka blocks.
125
+ """
126
+ pass_line_regex = re.compile(r"^\s*$|^#|^scc2020$")
127
+ def valid_line(line):
128
+ return pass_line_regex.match(line) is None
129
+ parse_line_regex = re.compile(r"^(?P<filtration>[^;]+);(?P<boundary>[^;]*)$")
130
+ cdef tuple[tuple[str,str]] clines
131
+ with open(path, "r") as f:
132
+ lines =(x.strip() for x in f if valid_line(x))
133
+ num_parameters = int(next(lines))
134
+ sizes = np.cumsum(np.asarray([0] + next(lines).split(), dtype=np.int32))
135
+ lines = (parse_line_regex.match(a) for a in lines)
136
+ clines = tuple((a.group("filtration"),a.group("boundary")) for a in lines)
137
+ # F = np.fromiter((a[0].split() for a in clines), dtype=np.dtype((np.float64,2)), count = sizes[-1])
138
+ F = np.fromiter((np.fromstring(a[0], sep=r' ', dtype=np.float64) for a in clines), dtype=np.dtype((np.float64,num_parameters)), count = sizes[-1])
139
+
140
+ # B = tuple(np.asarray(a[1].split(), dtype=np.int32) if len(a[1])>0 else np.empty(0, dtype=np.int32) for a in clines) ## TODO : this is very slow : optimize
141
+ B = tuple(np.fromstring(a[1], sep=' ', dtype=np.int32) for a in clines)
142
+ # block_lines = (tuple(get_bf(x, num_parameters) for x in lines[sizes[i]:sizes[i+1]]) for i in range(len(sizes)-1))
143
+
144
+ # blocks = [(np.asarray([x[0] for x in b if len(x)>0], dtype=float),tuple(x[1] for x in b)) for b in block_lines]
145
+ blocks = [(F[sizes[i]:sizes[i+1]], B[sizes[i]:sizes[i+1]]) for i in range(len(sizes)-1)]
146
+
147
+ return blocks
148
+
149
+
150
+
151
+
152
+ def _init_external_softwares(requires=[]):
153
+ global pathes
154
+ cdef bool any = False
155
+ for soft,soft_path in pathes.items():
156
+ if soft_path is None:
157
+ _path_init(soft)
158
+ any = any or (soft in requires)
159
+
160
+ if any:
161
+ for soft in requires:
162
+ if pathes[soft] is None:
163
+ global doc_soft_urls
164
+ raise ValueError(f"""
165
+ Did not find {soft}.
166
+ Install it from {doc_soft_urls[soft]}, and put it in your current directory,
167
+ or in you $PATH.
168
+ Documentation is available here: {current_doc_url}compilation.html#external-libraries
169
+ For instance:
170
+ {doc_soft_easy_install[soft]}
171
+ """)
172
+ _init_external_softwares()
173
+ def _check_available(soft:str):
174
+ _init_external_softwares()
175
+ return pathes.get(soft,None) is not None
176
+
177
+
178
+
179
+ def scc_reduce_from_str_to_slicer(
180
+ path:str|os.PathLike,
181
+ slicer,
182
+ bool full_resolution=True,
183
+ int dimension: int | np.int64 = 1,
184
+ bool clear: bool = True,
185
+ bool verbose:bool=False,
186
+ backend:Literal["mpfree","multi_chunk","twopac"]="mpfree",
187
+ shift_dimension=0
188
+ ):
189
+ """
190
+ Computes a minimal presentation of the file in path,
191
+ using mpfree.
192
+
193
+ path:PathLike
194
+ slicer: empty slicer to fill
195
+ full_resolution: bool
196
+ dimension: int, presentation dimension to consider
197
+ clear: bool, removes temporary files if True
198
+ verbose: bool
199
+ backend: "mpfree", "multi_chunk" or "2pac"
200
+ """
201
+ global pathes
202
+ _init_external_softwares(requires=[backend])
203
+
204
+ with tempfile.TemporaryDirectory(prefix="multipers", delete=clear) as tmpdir:
205
+ output_path = os.path.join(tmpdir, "multipers_output.scc")
206
+
207
+ resolution_str = "--resolution" if full_resolution else ""
208
+
209
+ if not os.path.exists(path):
210
+ raise ValueError(f"No file found at {path}.")
211
+
212
+ verbose_arg = "> /dev/null 2>&1" if not verbose else ""
213
+ if backend == "mpfree":
214
+ more_verbose = "-v" if verbose else ""
215
+ command = (
216
+ f"{pathes[backend]} {more_verbose} {resolution_str} --dim={dimension} {path} {output_path} {verbose_arg}"
217
+ )
218
+ elif backend == "multi_chunk":
219
+ command = (
220
+ f"{pathes[backend]} {path} {output_path} {verbose_arg}"
221
+ )
222
+ elif backend in ["twopac", "2pac"]:
223
+ command = (
224
+ f"{pathes[backend]} -f {path} --scc-input -n{dimension} --save-resolution-scc {output_path} {verbose_arg}"
225
+ )
226
+ else:
227
+ raise ValueError(f"Unsupported backend {backend}.")
228
+ if verbose:
229
+ print(f"Calling :\n\n {command}")
230
+ os.system(command)
231
+
232
+ slicer._build_from_scc_file(path=output_path, shift_dimension=shift_dimension)
233
+
234
+
235
+
236
+
237
+
238
+ def function_delaunay_presentation_to_slicer(
239
+ slicer,
240
+ point_cloud:np.ndarray,
241
+ function_values:np.ndarray,
242
+ bool clear:bool = True,
243
+ bool verbose:bool=False,
244
+ int degree = -1,
245
+ bool multi_chunk = False,
246
+ ):
247
+ """
248
+ Computes a function delaunay presentation, and returns it as a slicer.
249
+
250
+ slicer: empty slicer to fill
251
+ points : (num_pts, n) float array
252
+ grades : (num_pts,) float array
253
+ degree (opt) : if given, computes a minimal presentation of this homological degree first
254
+ clear:bool, removes temporary files if true
255
+ degree: computes minimal presentation of this degree if given
256
+ verbose : bool
257
+ """
258
+ global pathes
259
+
260
+ with tempfile.TemporaryDirectory(prefix="multipers", delete=clear) as tmpdir:
261
+ input_path = os.path.join(tmpdir, "multipers_input.scc")
262
+ output_path = os.path.join(tmpdir, "multipers_output.scc")
263
+
264
+ backend = "function_delaunay"
265
+ _init_external_softwares(requires=[backend])
266
+
267
+ to_write = np.concatenate([point_cloud, function_values.reshape(-1,1)], axis=1)
268
+ np.savetxt(input_path,to_write,delimiter=' ')
269
+ verbose_arg = "> /dev/null 2>&1" if not verbose else ""
270
+ degree_arg = f"--minpres {degree}" if degree >= 0 else ""
271
+ multi_chunk_arg = "--multi-chunk" if multi_chunk else ""
272
+ command = f"{pathes[backend]} {degree_arg} {multi_chunk_arg} {input_path} {output_path} {verbose_arg} --no-delaunay-compare"
273
+ if verbose:
274
+ print(command)
275
+ os.system(command)
276
+
277
+ slicer._build_from_scc_file(path=output_path, shift_dimension=-1 if degree <= 0 else degree-1 )
278
+
279
+ def _rhomboid_tiling_to_slicer(
280
+ slicer,
281
+ point_cloud:np.ndarray,
282
+ int k_max,
283
+ int degree = -1,
284
+ bool clear:bool = True,
285
+ bool verbose=False,
286
+ ):
287
+ """TODO"""
288
+ global pathes
289
+ backend = "rhomboid_tiling"
290
+ _init_external_softwares(requires=[backend])
291
+ if point_cloud.ndim != 2 or not point_cloud.shape[1] in [2,3]:
292
+ raise ValueError("point_cloud should be a 2d array of shape (-,2) or (-,3). Got {point_cloud.shape=}")
293
+ with tempfile.TemporaryDirectory(prefix="multipers", delete=clear) as tmpdir:
294
+ input_path = os.path.join(tmpdir, "point_cloud.txt")
295
+ output_path = os.path.join(tmpdir, "multipers_output.scc")
296
+ np.savetxt(input_path,point_cloud,delimiter=' ')
297
+
298
+ verbose_arg = "> /dev/null 2>&1" if not verbose else ""
299
+ command = f"{pathes[backend]} {input_path} {output_path} {point_cloud.shape[1]} {k_max} scc {degree} {verbose_arg}"
300
+ if verbose:
301
+ print(command)
302
+ os.system(command)
303
+ slicer._build_from_scc_file(path=output_path, shift_dimension=-1 if degree <= 0 else degree-1 )
304
+
305
+
306
+ def _multi_critical_from_slicer(
307
+ slicer,
308
+ bool reduce=False,
309
+ str algo:Literal["path","tree"]="path",
310
+ degree:Optional[int]=None,
311
+ bool clear = True,
312
+ swedish:Optional[bool] = None,
313
+ bool verbose = False,
314
+ bool kcritical=False,
315
+ **slicer_kwargs,
316
+ ):
317
+ _init_external_softwares(requires=["multi_critical"])
318
+ cdef bool need_split = False
319
+ swedish = degree is not None if swedish is None else swedish
320
+ from multipers import Slicer
321
+ newSlicer = Slicer(slicer,return_type_only=True, kcritical=kcritical, **slicer_kwargs)
322
+ with tempfile.TemporaryDirectory(prefix="multipers", delete=clear) as tmpdir:
323
+ input_path = os.path.join(tmpdir, "multipers_input.scc")
324
+ output_path = os.path.join(tmpdir, "multipers_output.scc")
325
+ slicer.to_scc(input_path, degree=0, strip_comments=True)
326
+ reduce_arg = ""
327
+ if reduce:
328
+ if swedish:
329
+ reduce_arg += r" --swedish"
330
+ if degree is None:
331
+ need_split = True
332
+ reduce_arg += r" --minpres-all"
333
+ else:
334
+ reduce_arg += fr" --minpres {slicer.dimension - degree+2}"
335
+ verbose_arg = "> /dev/null 2>&1" if not verbose else ""
336
+
337
+ command = f"{pathes['multi_critical']} --{algo} {reduce_arg} {input_path} {output_path} {verbose_arg}"
338
+ if verbose:
339
+ print(command)
340
+ os.system(command)
341
+ if need_split:
342
+ os.system(f"awk \'/scc2020/ {{n++}} {{print > (\"{tmpdir}/multipers_block_\" n \".scc\")}}\' {output_path}")
343
+ from glob import glob
344
+ import re
345
+ files = glob(tmpdir + "/multipers_block_*.scc")
346
+ files.sort(key=lambda f: int(re.search(r'\d+', f).group()))
347
+ num_degrees=len(files)
348
+ ss = tuple(newSlicer()._build_from_scc_file(files[i], shift_dimension=i-1).minpres(i) for i in range(num_degrees))
349
+ return ss
350
+ out = newSlicer()._build_from_scc_file(str(output_path), shift_dimension=degree-1 if reduce else -2)
351
+ if reduce:
352
+ out = out.minpres(degree)
353
+ return out
354
+
355
+
356
+
357
+ @cython.boundscheck(False)
358
+ @cython.wraparound(False)
359
+ def scc2disk(
360
+ stuff,
361
+ path:str|os.PathLike,
362
+ int num_parameters = -1,
363
+ bool reverse_block = False,
364
+ bool rivet_compatible = False,
365
+ bool ignore_last_generators = False,
366
+ bool strip_comments = False,
367
+ ):
368
+ """
369
+ Writes a scc python format / blocks into a file.
370
+ """
371
+ if num_parameters == -1:
372
+ for block in stuff:
373
+ if len(block[0]) == 0:
374
+ continue
375
+ num_gens, num_parameters_= np.asarray(block[0]).shape
376
+ num_parameters = num_parameters_
377
+ break
378
+ assert num_parameters > 0, f"Invalid number of parameters {num_parameters}"
379
+
380
+ if reverse_block: stuff.reverse()
381
+ with open(path, "w") as f:
382
+ f.write("scc2020\n") if not rivet_compatible else f.write("firep\n")
383
+ if not strip_comments and not rivet_compatible: f.write("# Number of parameters\n")
384
+ if rivet_compatible:
385
+ assert num_parameters == 2
386
+ f.write("Filtration 1\n")
387
+ f.write("Filtration 2\n")
388
+ else:
389
+ f.write(f"{num_parameters}\n")
390
+
391
+ if not strip_comments: f.write("# Sizes of generating sets\n")
392
+ for block in stuff: f.write(f"{len(block[0])} ")
393
+ f.write("\n")
394
+ for i,block in enumerate(stuff):
395
+ if (rivet_compatible or ignore_last_generators) and i == len(stuff)-1: continue
396
+ if not strip_comments: f.write(f"# Block of dimension {len(stuff)-1-i}\n")
397
+ filtration, boundary = block
398
+ filtration = np.asarray(filtration).astype(str)
399
+ # boundary = tuple(x.astype(str) for x in boundary)
400
+ f.write(" ".join(itertools.chain.from_iterable(
401
+ ((*(f.tolist()), ";", *(np.asarray(b).astype(str).tolist()), "\n")
402
+ for f,b in zip(filtration, boundary))
403
+ )
404
+ ))
405
+ # for j in range(<int>len(filtration)):
406
+ # line = " ".join((
407
+ # *filtration[j],
408
+ # ";",
409
+ # *boundary[j],
410
+ # "\n",
411
+ # ))
412
+ # f.write(line)
413
+
414
+ def scc2disk_old(
415
+ stuff,
416
+ path:str|os.PathLike,
417
+ num_parameters = -1,
418
+ reverse_block = False,
419
+ rivet_compatible = False,
420
+ ignore_last_generators = False,
421
+ strip_comments = False,
422
+ ):
423
+ """
424
+ Writes a scc python format / blocks into a file.
425
+ """
426
+ if num_parameters == -1:
427
+ for block in stuff:
428
+ if len(block[0]) == 0:
429
+ continue
430
+ num_gens, num_parameters_= np.asarray(block[0]).shape
431
+ num_parameters = num_parameters_
432
+ break
433
+ assert num_parameters > 0, f"Invalid number of parameters {num_parameters}"
434
+
435
+ if reverse_block: stuff.reverse()
436
+ out = []
437
+ if rivet_compatible:
438
+ out.append(r"firep")
439
+ else:
440
+ out.append(r"scc2020")
441
+ if not strip_comments and not rivet_compatible:
442
+ out.append(r"# Number of parameters")
443
+ if rivet_compatible:
444
+ out.append("Filtration 1")
445
+ out.append("Filtration 2\n")
446
+ else:
447
+ out.append(f"{num_parameters}")
448
+
449
+ if not strip_comments:
450
+ out.append("# Sizes of generating sets")
451
+
452
+ # for block in stuff:
453
+ # f.write(f"{len(block[0])} ")
454
+ out.append(" ".join(str(len(block[0])) for block in stuff))
455
+ str_blocks = [out]
456
+ for i,block in enumerate(stuff):
457
+ if (rivet_compatible or ignore_last_generators) and i == len(stuff)-1: continue
458
+ if not strip_comments:
459
+ str_blocks.append([f"# Block of dimension {len(stuff)-1-i}"])
460
+ filtration, boundary = block
461
+ if len(filtration) == 0:
462
+ continue
463
+ filtration = filtration.astype(str)
464
+ C = filtration[:,0]
465
+ for i in range(1,filtration.shape[1]):
466
+ C = np.char.add(C," ")
467
+ C = np.char.add(C,filtration[:,i])
468
+ C = np.char.add(C, ";")
469
+ D = np.fromiter((" ".join(b.astype(str).tolist()) for b in boundary), dtype="<U11") #int32-> str is "<U11" #check np.array(1, dtype=np.int32).astype(str)
470
+ str_blocks.append(np.char.add(C,D))
471
+
472
+ np.savetxt("test.scc", np.concatenate(str_blocks), delimiter="", fmt="%s")
File without changes
@@ -0,0 +1,90 @@
1
+ import pandas as pd
2
+ from warnings import warn
3
+ import numpy as np
4
+ from tqdm import tqdm
5
+ from os.path import exists
6
+
7
+
8
+ def accuracy_to_csv(
9
+ X,
10
+ Y,
11
+ cl,
12
+ k: float = 10,
13
+ dataset: str = "",
14
+ shuffle=True,
15
+ verbose: bool = True,
16
+ **more_columns,
17
+ ):
18
+ assert k > 0, "k is either the number of kfold > 1 or the test size > 0."
19
+ if k > 1:
20
+ k = int(k)
21
+ from sklearn.model_selection import StratifiedKFold as KFold
22
+
23
+ kfold = KFold(k, shuffle=shuffle).split(X, Y)
24
+ accuracies = np.zeros(k)
25
+ for i, (train_idx, test_idx) in enumerate(
26
+ tqdm(kfold, total=k, desc="Computing kfold")
27
+ ):
28
+ xtrain = [X[i] for i in train_idx]
29
+ ytrain = [Y[i] for i in train_idx]
30
+ cl.fit(xtrain, ytrain)
31
+ xtest = [X[i] for i in test_idx]
32
+ ytest = [Y[i] for i in test_idx]
33
+ accuracies[i] = cl.score(xtest, ytest)
34
+ if verbose:
35
+ print(f"step {i+1}, {dataset} : {accuracies[i]}", flush=True)
36
+ try:
37
+ print("Best classification parameters : ", cl.best_params_)
38
+ except:
39
+ None
40
+
41
+ print(
42
+ f"""Accuracy {dataset} : {np.mean(accuracies).round(decimals=3)}±{np.std(accuracies).round(decimals=3)}"""
43
+ )
44
+ elif k > 0:
45
+ from sklearn.model_selection import train_test_split
46
+
47
+ print("Computing accuracy, with train test split", flush=True)
48
+ xtrain, xtest, ytrain, ytest = train_test_split(
49
+ X, Y, shuffle=shuffle, test_size=k
50
+ )
51
+ print("Fitting...", end="", flush=True)
52
+ cl.fit(xtrain, ytrain)
53
+ print("Computing score...", end="", flush=True)
54
+ accuracies = cl.score(xtest, ytest)
55
+ try:
56
+ print("Best classification parameters : ", cl.best_params_)
57
+ except:
58
+ None
59
+ print("Done.")
60
+ if verbose:
61
+ print(f"Accuracy {dataset} : {accuracies} ")
62
+ file_path: str = f"result_{dataset}.csv".replace("/", "_").replace(".off", "")
63
+ columns: list[str] = ["dataset", "cv", "mean", "std"]
64
+ if exists(file_path):
65
+ df: pd.DataFrame = pd.read_csv(file_path)
66
+ else:
67
+ df: pd.DataFrame = pd.DataFrame(columns=columns)
68
+ more_names = []
69
+ more_values = []
70
+ for key, value in more_columns.items():
71
+ if key not in columns:
72
+ more_names.append(key)
73
+ more_values.append(value)
74
+ else:
75
+ warn(f"Duplicate key {key} ! with value {value}")
76
+ new_line: pd.DataFrame = pd.DataFrame(
77
+ [
78
+ [
79
+ dataset,
80
+ k,
81
+ np.mean(accuracies).round(decimals=3),
82
+ np.std(accuracies).round(decimals=3),
83
+ ]
84
+ + more_values
85
+ ],
86
+ columns=columns + more_names,
87
+ )
88
+ print(new_line)
89
+ df = pd.concat([df, new_line])
90
+ df.to_csv(file_path, index=False)
@@ -0,0 +1,79 @@
1
+ import persistable
2
+
3
+
4
+ # requires installing ripser (pip install ripser) as well as persistable from the higher-homology branch,
5
+ # which can be done as follows:
6
+ # pip install git+https://github.com/LuisScoccola/persistable.git@higher-homology
7
+ # NOTE: only accepts as input a distance matrix
8
+ def hf_degree_rips(
9
+ distance_matrix,
10
+ min_rips_value,
11
+ max_rips_value,
12
+ max_normalized_degree,
13
+ min_normalized_degree,
14
+ grid_granularity,
15
+ max_homological_dimension,
16
+ subsample_size = None,
17
+ ):
18
+ if subsample_size == None:
19
+ p = persistable.Persistable(distance_matrix, metric="precomputed")
20
+ else:
21
+ p = persistable.Persistable(distance_matrix, metric="precomputed", subsample=subsample_size)
22
+
23
+ rips_values, normalized_degree_values, hilbert_functions, minimal_hilbert_decompositions = p._hilbert_function(
24
+ min_rips_value,
25
+ max_rips_value,
26
+ max_normalized_degree,
27
+ min_normalized_degree,
28
+ grid_granularity,
29
+ homological_dimension=max_homological_dimension,
30
+ )
31
+
32
+ return rips_values, normalized_degree_values, hilbert_functions, minimal_hilbert_decompositions
33
+
34
+
35
+
36
+ def hf_h0_degree_rips(
37
+ point_cloud,
38
+ min_rips_value,
39
+ max_rips_value,
40
+ max_normalized_degree,
41
+ min_normalized_degree,
42
+ grid_granularity,
43
+ ):
44
+ p = persistable.Persistable(point_cloud, n_neighbors="all")
45
+
46
+ rips_values, normalized_degree_values, hilbert_functions, minimal_hilbert_decompositions = p._hilbert_function(
47
+ min_rips_value,
48
+ max_rips_value,
49
+ max_normalized_degree,
50
+ min_normalized_degree,
51
+ grid_granularity,
52
+ )
53
+
54
+ return rips_values, normalized_degree_values, hilbert_functions[0], minimal_hilbert_decompositions[0]
55
+
56
+
57
+ def ri_h0_degree_rips(
58
+ point_cloud,
59
+ min_rips_value,
60
+ max_rips_value,
61
+ max_normalized_degree,
62
+ min_normalized_degree,
63
+ grid_granularity,
64
+ ):
65
+ p = persistable.Persistable(point_cloud, n_neighbors="all")
66
+
67
+ rips_values, normalized_degree_values, rank_invariant, _, _ = p._rank_invariant(
68
+ min_rips_value,
69
+ max_rips_value,
70
+ max_normalized_degree,
71
+ min_normalized_degree,
72
+ grid_granularity,
73
+ )
74
+
75
+ return rips_values, normalized_degree_values, rank_invariant
76
+
77
+
78
+
79
+