multipers 1.2.2__cp310-cp310-macosx_10_13_x86_64.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.
- multipers/.dylibs/libc++.1.0.dylib +0 -0
- multipers/.dylibs/libtbb.12.12.dylib +0 -0
- multipers/.dylibs/libtbbmalloc.2.12.dylib +0 -0
- multipers/__init__.py +11 -0
- multipers/_signed_measure_meta.py +268 -0
- multipers/_slicer_meta.py +171 -0
- multipers/data/MOL2.py +350 -0
- multipers/data/UCR.py +18 -0
- multipers/data/__init__.py +1 -0
- multipers/data/graphs.py +466 -0
- multipers/data/immuno_regions.py +27 -0
- multipers/data/minimal_presentation_to_st_bf.py +0 -0
- multipers/data/pytorch2simplextree.py +91 -0
- multipers/data/shape3d.py +101 -0
- multipers/data/synthetic.py +68 -0
- multipers/distances.py +198 -0
- multipers/euler_characteristic.pyx +132 -0
- multipers/filtration_conversions.pxd +229 -0
- multipers/filtrations.pxd +225 -0
- multipers/function_rips.cpython-310-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-310-darwin.so +0 -0
- multipers/grids.pyx +281 -0
- multipers/hilbert_function.pyi +46 -0
- multipers/hilbert_function.pyx +153 -0
- multipers/io.cpython-310-darwin.so +0 -0
- multipers/io.pyx +571 -0
- multipers/ml/__init__.py +0 -0
- multipers/ml/accuracies.py +90 -0
- multipers/ml/convolutions.py +532 -0
- multipers/ml/invariants_with_persistable.py +79 -0
- multipers/ml/kernels.py +176 -0
- multipers/ml/mma.py +659 -0
- multipers/ml/one.py +472 -0
- multipers/ml/point_clouds.py +238 -0
- multipers/ml/signed_betti.py +50 -0
- multipers/ml/signed_measures.py +1542 -0
- multipers/ml/sliced_wasserstein.py +461 -0
- multipers/ml/tools.py +113 -0
- multipers/mma_structures.cpython-310-darwin.so +0 -0
- multipers/mma_structures.pxd +127 -0
- multipers/mma_structures.pyx +2433 -0
- multipers/multiparameter_edge_collapse.py +41 -0
- multipers/multiparameter_module_approximation.cpython-310-darwin.so +0 -0
- multipers/multiparameter_module_approximation.pyx +211 -0
- multipers/pickle.py +53 -0
- multipers/plots.py +326 -0
- multipers/point_measure_integration.cpython-310-darwin.so +0 -0
- multipers/point_measure_integration.pyx +139 -0
- multipers/rank_invariant.cpython-310-darwin.so +0 -0
- multipers/rank_invariant.pyx +229 -0
- multipers/simplex_tree_multi.cpython-310-darwin.so +0 -0
- multipers/simplex_tree_multi.pxd +129 -0
- multipers/simplex_tree_multi.pyi +715 -0
- multipers/simplex_tree_multi.pyx +4655 -0
- multipers/slicer.cpython-310-darwin.so +0 -0
- multipers/slicer.pxd +781 -0
- multipers/slicer.pyx +3393 -0
- multipers/tensor.pxd +13 -0
- multipers/test.pyx +44 -0
- multipers/tests/__init__.py +40 -0
- multipers/tests/old_test_rank_invariant.py +91 -0
- multipers/tests/test_diff_helper.py +74 -0
- multipers/tests/test_hilbert_function.py +82 -0
- multipers/tests/test_mma.py +51 -0
- multipers/tests/test_point_clouds.py +59 -0
- multipers/tests/test_python-cpp_conversion.py +82 -0
- multipers/tests/test_signed_betti.py +181 -0
- multipers/tests/test_simplextreemulti.py +98 -0
- multipers/tests/test_slicer.py +63 -0
- multipers/torch/__init__.py +1 -0
- multipers/torch/diff_grids.py +217 -0
- multipers/torch/rips_density.py +257 -0
- multipers-1.2.2.dist-info/LICENSE +21 -0
- multipers-1.2.2.dist-info/METADATA +28 -0
- multipers-1.2.2.dist-info/RECORD +78 -0
- multipers-1.2.2.dist-info/WHEEL +5 -0
- multipers-1.2.2.dist-info/top_level.txt +1 -0
multipers/slicer.pyx
ADDED
|
@@ -0,0 +1,3393 @@
|
|
|
1
|
+
# WARNING: Do not edit this file directly.
|
|
2
|
+
# It is automatically generated from 'multipers/slicer.pyx.tp'.
|
|
3
|
+
# Changes must be made there.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from multipers.simplex_tree_multi import SimplexTreeMulti
|
|
7
|
+
import multipers
|
|
8
|
+
from typing import Optional,Literal
|
|
9
|
+
import multipers.io as mio
|
|
10
|
+
import multipers.grids as mpg
|
|
11
|
+
import threading
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from multipers.slicer cimport *
|
|
15
|
+
from multipers.filtrations cimport *
|
|
16
|
+
from multipers.filtration_conversions cimport *
|
|
17
|
+
import numpy as np
|
|
18
|
+
cimport cython
|
|
19
|
+
# python_value_type = np.float32
|
|
20
|
+
from typing import Union
|
|
21
|
+
|
|
22
|
+
global available_slicers
|
|
23
|
+
available_slicers = tuple((
|
|
24
|
+
_SlicerClement,
|
|
25
|
+
_SlicerVineGraph,
|
|
26
|
+
_SlicerVineSimplicial,
|
|
27
|
+
_SlicerNoVineSimplicial,
|
|
28
|
+
_KSlicer0_vine_i32,
|
|
29
|
+
_KSlicer0_vine_f32,
|
|
30
|
+
_KSlicer0_vine_f64,
|
|
31
|
+
_Slicer0_vine_i32,
|
|
32
|
+
_Slicer0_vine_f32,
|
|
33
|
+
_Slicer0_vine_f64,
|
|
34
|
+
_KSlicer0_i32,
|
|
35
|
+
_KSlicer0_f32,
|
|
36
|
+
_KSlicer0_f64,
|
|
37
|
+
_Slicer0_i32,
|
|
38
|
+
_Slicer0_f32,
|
|
39
|
+
_Slicer0_f64,
|
|
40
|
+
))
|
|
41
|
+
global _slicers_type
|
|
42
|
+
Slicer_type = Union[
|
|
43
|
+
_SlicerClement,
|
|
44
|
+
_SlicerVineGraph,
|
|
45
|
+
_SlicerVineSimplicial,
|
|
46
|
+
_SlicerNoVineSimplicial,
|
|
47
|
+
_KSlicer0_vine_i32,
|
|
48
|
+
_KSlicer0_vine_f32,
|
|
49
|
+
_KSlicer0_vine_f64,
|
|
50
|
+
_Slicer0_vine_i32,
|
|
51
|
+
_Slicer0_vine_f32,
|
|
52
|
+
_Slicer0_vine_f64,
|
|
53
|
+
_KSlicer0_i32,
|
|
54
|
+
_KSlicer0_f32,
|
|
55
|
+
_KSlicer0_f64,
|
|
56
|
+
_Slicer0_i32,
|
|
57
|
+
_Slicer0_f32,
|
|
58
|
+
_Slicer0_f64,
|
|
59
|
+
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
#------------------------------------------------------------------------------
|
|
64
|
+
cdef class _SlicerClement:
|
|
65
|
+
cdef GeneralVineClementTruc truc
|
|
66
|
+
cdef public vector[vector[double]] filtration_grid
|
|
67
|
+
@property
|
|
68
|
+
def is_squeezed(self)->bool:
|
|
69
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
70
|
+
|
|
71
|
+
def get_ptr(self):
|
|
72
|
+
"""
|
|
73
|
+
Returns a pointer to the underlying C++ slicer.
|
|
74
|
+
"""
|
|
75
|
+
return <intptr_t>(&self.truc)
|
|
76
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
77
|
+
"""
|
|
78
|
+
Constructs a slicer from
|
|
79
|
+
- generator maps (Iterable of list of ints)
|
|
80
|
+
- generator dimensions (Iterable of int)
|
|
81
|
+
- filtration values (Iterable of filtration values)
|
|
82
|
+
"""
|
|
83
|
+
pass
|
|
84
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
85
|
+
"""
|
|
86
|
+
Cython constructor
|
|
87
|
+
"""
|
|
88
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
89
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
90
|
+
cdef vector[Finitely_critical_multi_filtration[float]] c_filtration_values
|
|
91
|
+
for stuff in generator_maps:
|
|
92
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
93
|
+
for f in filtration_values:
|
|
94
|
+
# cf.clear()
|
|
95
|
+
# for truc in f:
|
|
96
|
+
# cf.push_back(truc)
|
|
97
|
+
c_filtration_values.push_back(_py21c_f32(f))
|
|
98
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
99
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
100
|
+
self.truc = GeneralVineClementTruc(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
101
|
+
def copy(self):
|
|
102
|
+
"""
|
|
103
|
+
Returns a copy of the slicer.
|
|
104
|
+
"""
|
|
105
|
+
copy_ = _SlicerClement()
|
|
106
|
+
copy_.truc = self.truc
|
|
107
|
+
return copy_
|
|
108
|
+
def get_barcode(self):
|
|
109
|
+
"""
|
|
110
|
+
Returns the current barcode.
|
|
111
|
+
"""
|
|
112
|
+
return self.truc.get_barcode()
|
|
113
|
+
def push_to_line(self, basepoint, direction=None):
|
|
114
|
+
"""
|
|
115
|
+
Pushes the current slicer to the line
|
|
116
|
+
"""
|
|
117
|
+
cdef Line[float] line
|
|
118
|
+
if direction is None:
|
|
119
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
120
|
+
else:
|
|
121
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
122
|
+
self.truc.push_to(line)
|
|
123
|
+
return self
|
|
124
|
+
|
|
125
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
126
|
+
"""
|
|
127
|
+
Computes the persistence on a line L defined by
|
|
128
|
+
- a basepoint (num_parameters,) array
|
|
129
|
+
- an optional direction (num_parameters,) array
|
|
130
|
+
"""
|
|
131
|
+
self.push_to_line(basepoint,direction)
|
|
132
|
+
self.truc.compute_persistence()
|
|
133
|
+
return self.truc.get_barcode()
|
|
134
|
+
def compute_persistence(self,one_filtration=None):
|
|
135
|
+
"""
|
|
136
|
+
Computes the current persistence, or the persistence
|
|
137
|
+
given by the filtration one_filtration (num_generators,).
|
|
138
|
+
"""
|
|
139
|
+
if one_filtration is not None:
|
|
140
|
+
self.truc.set_one_filtration(one_filtration)
|
|
141
|
+
self.truc.compute_persistence()
|
|
142
|
+
# return self.truc.get_barcode()
|
|
143
|
+
def get_barcode(self):
|
|
144
|
+
"""
|
|
145
|
+
Returns the barcode of the current 1d-persistence.
|
|
146
|
+
"""
|
|
147
|
+
return self.truc.get_barcode()
|
|
148
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
149
|
+
"""
|
|
150
|
+
Computes the filtration on a line L defined by
|
|
151
|
+
- a basepoint (num_parameters,) array
|
|
152
|
+
- an optional direction (num_parameters,) array
|
|
153
|
+
"""
|
|
154
|
+
self.push_to_line(basepoint,direction)
|
|
155
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
156
|
+
def __len__(self):
|
|
157
|
+
return self.truc.num_generators()
|
|
158
|
+
@property
|
|
159
|
+
def num_generators(self):
|
|
160
|
+
return self.truc.num_generators()
|
|
161
|
+
@property
|
|
162
|
+
def num_parameters(self):
|
|
163
|
+
return self.truc.num_parameters()
|
|
164
|
+
def info(self):
|
|
165
|
+
return self.truc.to_str().decode()
|
|
166
|
+
def compute_box(self):
|
|
167
|
+
"""
|
|
168
|
+
Computes the bounding box of the current persistence.
|
|
169
|
+
"""
|
|
170
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
171
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
172
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
173
|
+
return np.asarray([a,b])
|
|
174
|
+
def get_filtrations_values(self):
|
|
175
|
+
"""
|
|
176
|
+
Returns the current filtration values of the slicer.
|
|
177
|
+
"""
|
|
178
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
179
|
+
out = _vff21cview_f32(v, copy=True)
|
|
180
|
+
return np.asarray(out)
|
|
181
|
+
def get_filtrations(self):
|
|
182
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
183
|
+
|
|
184
|
+
def get_dimensions(self):
|
|
185
|
+
"""
|
|
186
|
+
Returns the ordered dimensions of the generators.
|
|
187
|
+
"""
|
|
188
|
+
return np.asarray(self.truc.get_dimensions())
|
|
189
|
+
def get_boundaries(self):
|
|
190
|
+
"""
|
|
191
|
+
Returns the boundaries of the generators.
|
|
192
|
+
"""
|
|
193
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
194
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
195
|
+
"""
|
|
196
|
+
Squeeze the filtration values on a grid.
|
|
197
|
+
"""
|
|
198
|
+
if force and self.is_squeezed:
|
|
199
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
200
|
+
if filtration_grid is None:
|
|
201
|
+
filtration_grid = mpg.compute_grid(
|
|
202
|
+
self.get_filtrations_values().T,
|
|
203
|
+
strategy=grid_strategy,
|
|
204
|
+
resolution=resolution)
|
|
205
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
206
|
+
if inplace or not coordinates:
|
|
207
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
208
|
+
self.filtration_grid = filtration_grid
|
|
209
|
+
else:
|
|
210
|
+
raise ValueError("WIP")
|
|
211
|
+
return self
|
|
212
|
+
def minpres(self,
|
|
213
|
+
int degree = 1,
|
|
214
|
+
list[int] degrees=[],
|
|
215
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
216
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
217
|
+
bool vineyard=True,
|
|
218
|
+
id :Optional[str] = None,
|
|
219
|
+
dtype = np.float32,
|
|
220
|
+
**minpres_kwargs
|
|
221
|
+
):
|
|
222
|
+
"""
|
|
223
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
224
|
+
"""
|
|
225
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
226
|
+
return new_slicer
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def dtype(self)->type:
|
|
230
|
+
return np.float32
|
|
231
|
+
@property
|
|
232
|
+
def col_type(self)->str:
|
|
233
|
+
return ""
|
|
234
|
+
@property
|
|
235
|
+
def is_vine(self)->bool:
|
|
236
|
+
return True
|
|
237
|
+
@property
|
|
238
|
+
def is_kcritical(self)->bool:
|
|
239
|
+
return False
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def vine_update(self,basepoint,direction=None):
|
|
243
|
+
"""
|
|
244
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
245
|
+
"""
|
|
246
|
+
self.push_to_line(basepoint,direction)
|
|
247
|
+
self.truc.vineyard_update()
|
|
248
|
+
return self
|
|
249
|
+
def get_representative_cycles(self, bool update=True):
|
|
250
|
+
"""
|
|
251
|
+
Returns the representative cycles of the current barcode.
|
|
252
|
+
Recomputes the generators if update=True
|
|
253
|
+
"""
|
|
254
|
+
return self.truc.get_representative_cycles(update)
|
|
255
|
+
def get_permutation(self):
|
|
256
|
+
"""
|
|
257
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
258
|
+
"""
|
|
259
|
+
return self.truc.get_current_order()
|
|
260
|
+
|
|
261
|
+
@staticmethod
|
|
262
|
+
def from_bitmap(self):
|
|
263
|
+
raise ValueError("Not implemented.")
|
|
264
|
+
|
|
265
|
+
#------------------------------------------------------------------------------
|
|
266
|
+
cdef class _SlicerVineGraph:
|
|
267
|
+
cdef SimplicialVineGraphTruc truc
|
|
268
|
+
cdef public vector[vector[double]] filtration_grid
|
|
269
|
+
@property
|
|
270
|
+
def is_squeezed(self)->bool:
|
|
271
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
272
|
+
|
|
273
|
+
def get_ptr(self):
|
|
274
|
+
"""
|
|
275
|
+
Returns a pointer to the underlying C++ slicer.
|
|
276
|
+
"""
|
|
277
|
+
return <intptr_t>(&self.truc)
|
|
278
|
+
def __init__(self, st=None):
|
|
279
|
+
"""
|
|
280
|
+
Constructs a slicer from a simplex tree.
|
|
281
|
+
"""
|
|
282
|
+
pass
|
|
283
|
+
def __cinit__(self, st=None):
|
|
284
|
+
if st is None:
|
|
285
|
+
return
|
|
286
|
+
cdef intptr_t ptr = st.thisptr
|
|
287
|
+
cdef Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]* st_ptr = <Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]*>(ptr)
|
|
288
|
+
self.truc = SimplicialVineGraphTruc(st_ptr)
|
|
289
|
+
def copy(self):
|
|
290
|
+
"""
|
|
291
|
+
Returns a copy of the slicer.
|
|
292
|
+
"""
|
|
293
|
+
copy_ = _SlicerVineGraph()
|
|
294
|
+
copy_.truc = self.truc
|
|
295
|
+
return copy_
|
|
296
|
+
def get_barcode(self):
|
|
297
|
+
"""
|
|
298
|
+
Returns the current barcode.
|
|
299
|
+
"""
|
|
300
|
+
return self.truc.get_barcode()
|
|
301
|
+
def push_to_line(self, basepoint, direction=None):
|
|
302
|
+
"""
|
|
303
|
+
Pushes the current slicer to the line
|
|
304
|
+
"""
|
|
305
|
+
cdef Line[float] line
|
|
306
|
+
if direction is None:
|
|
307
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
308
|
+
else:
|
|
309
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
310
|
+
self.truc.push_to(line)
|
|
311
|
+
return self
|
|
312
|
+
|
|
313
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
314
|
+
"""
|
|
315
|
+
Computes the persistence on a line L defined by
|
|
316
|
+
- a basepoint (num_parameters,) array
|
|
317
|
+
- an optional direction (num_parameters,) array
|
|
318
|
+
"""
|
|
319
|
+
self.push_to_line(basepoint,direction)
|
|
320
|
+
self.truc.compute_persistence()
|
|
321
|
+
return self.truc.get_barcode()
|
|
322
|
+
def compute_persistence(self,one_filtration=None):
|
|
323
|
+
"""
|
|
324
|
+
Computes the current persistence, or the persistence
|
|
325
|
+
given by the filtration one_filtration (num_generators,).
|
|
326
|
+
"""
|
|
327
|
+
if one_filtration is not None:
|
|
328
|
+
self.truc.set_one_filtration(one_filtration)
|
|
329
|
+
self.truc.compute_persistence()
|
|
330
|
+
# return self.truc.get_barcode()
|
|
331
|
+
def get_barcode(self):
|
|
332
|
+
"""
|
|
333
|
+
Returns the barcode of the current 1d-persistence.
|
|
334
|
+
"""
|
|
335
|
+
return self.truc.get_barcode()
|
|
336
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
337
|
+
"""
|
|
338
|
+
Computes the filtration on a line L defined by
|
|
339
|
+
- a basepoint (num_parameters,) array
|
|
340
|
+
- an optional direction (num_parameters,) array
|
|
341
|
+
"""
|
|
342
|
+
self.push_to_line(basepoint,direction)
|
|
343
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
344
|
+
def __len__(self):
|
|
345
|
+
return self.truc.num_generators()
|
|
346
|
+
@property
|
|
347
|
+
def num_generators(self):
|
|
348
|
+
return self.truc.num_generators()
|
|
349
|
+
@property
|
|
350
|
+
def num_parameters(self):
|
|
351
|
+
return self.truc.num_parameters()
|
|
352
|
+
def info(self):
|
|
353
|
+
return self.truc.to_str().decode()
|
|
354
|
+
def compute_box(self):
|
|
355
|
+
"""
|
|
356
|
+
Computes the bounding box of the current persistence.
|
|
357
|
+
"""
|
|
358
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
359
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
360
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
361
|
+
return np.asarray([a,b])
|
|
362
|
+
def get_filtrations_values(self):
|
|
363
|
+
"""
|
|
364
|
+
Returns the current filtration values of the slicer.
|
|
365
|
+
"""
|
|
366
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
367
|
+
out = _vff21cview_f32(v, copy=True)
|
|
368
|
+
return np.asarray(out)
|
|
369
|
+
def get_filtrations(self):
|
|
370
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
371
|
+
|
|
372
|
+
def get_dimensions(self):
|
|
373
|
+
"""
|
|
374
|
+
Returns the ordered dimensions of the generators.
|
|
375
|
+
"""
|
|
376
|
+
return np.asarray(self.truc.get_dimensions())
|
|
377
|
+
def get_boundaries(self):
|
|
378
|
+
"""
|
|
379
|
+
Returns the boundaries of the generators.
|
|
380
|
+
"""
|
|
381
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
382
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
383
|
+
"""
|
|
384
|
+
Squeeze the filtration values on a grid.
|
|
385
|
+
"""
|
|
386
|
+
if force and self.is_squeezed:
|
|
387
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
388
|
+
if filtration_grid is None:
|
|
389
|
+
filtration_grid = mpg.compute_grid(
|
|
390
|
+
self.get_filtrations_values().T,
|
|
391
|
+
strategy=grid_strategy,
|
|
392
|
+
resolution=resolution)
|
|
393
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
394
|
+
if inplace or not coordinates:
|
|
395
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
396
|
+
self.filtration_grid = filtration_grid
|
|
397
|
+
else:
|
|
398
|
+
raise ValueError("WIP")
|
|
399
|
+
return self
|
|
400
|
+
def minpres(self,
|
|
401
|
+
int degree = 1,
|
|
402
|
+
list[int] degrees=[],
|
|
403
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
404
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
405
|
+
bool vineyard=True,
|
|
406
|
+
id :Optional[str] = None,
|
|
407
|
+
dtype = np.float32,
|
|
408
|
+
**minpres_kwargs
|
|
409
|
+
):
|
|
410
|
+
"""
|
|
411
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
412
|
+
"""
|
|
413
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
414
|
+
return new_slicer
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def dtype(self)->type:
|
|
418
|
+
return np.float32
|
|
419
|
+
@property
|
|
420
|
+
def col_type(self)->str:
|
|
421
|
+
return ""
|
|
422
|
+
@property
|
|
423
|
+
def is_vine(self)->bool:
|
|
424
|
+
return True
|
|
425
|
+
@property
|
|
426
|
+
def is_kcritical(self)->bool:
|
|
427
|
+
return False
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def vine_update(self,basepoint,direction=None):
|
|
431
|
+
"""
|
|
432
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
433
|
+
"""
|
|
434
|
+
self.push_to_line(basepoint,direction)
|
|
435
|
+
self.truc.vineyard_update()
|
|
436
|
+
return self
|
|
437
|
+
def get_representative_cycles(self, bool update=True):
|
|
438
|
+
"""
|
|
439
|
+
Returns the representative cycles of the current barcode.
|
|
440
|
+
Recomputes the generators if update=True
|
|
441
|
+
"""
|
|
442
|
+
return self.truc.get_representative_cycles(update)
|
|
443
|
+
def get_permutation(self):
|
|
444
|
+
"""
|
|
445
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
446
|
+
"""
|
|
447
|
+
return self.truc.get_current_order()
|
|
448
|
+
|
|
449
|
+
@staticmethod
|
|
450
|
+
def from_bitmap(self):
|
|
451
|
+
raise ValueError("Not implemented.")
|
|
452
|
+
|
|
453
|
+
#------------------------------------------------------------------------------
|
|
454
|
+
cdef class _SlicerVineSimplicial:
|
|
455
|
+
cdef SimplicialVineMatrixTruc truc
|
|
456
|
+
cdef public vector[vector[double]] filtration_grid
|
|
457
|
+
@property
|
|
458
|
+
def is_squeezed(self)->bool:
|
|
459
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
460
|
+
|
|
461
|
+
def get_ptr(self):
|
|
462
|
+
"""
|
|
463
|
+
Returns a pointer to the underlying C++ slicer.
|
|
464
|
+
"""
|
|
465
|
+
return <intptr_t>(&self.truc)
|
|
466
|
+
def __init__(self, st=None):
|
|
467
|
+
"""
|
|
468
|
+
Constructs a slicer from a simplex tree.
|
|
469
|
+
"""
|
|
470
|
+
pass
|
|
471
|
+
def __cinit__(self, st=None):
|
|
472
|
+
if st is None:
|
|
473
|
+
return
|
|
474
|
+
cdef intptr_t ptr = st.thisptr
|
|
475
|
+
cdef Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]* st_ptr = <Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]*>(ptr)
|
|
476
|
+
self.truc = SimplicialVineMatrixTruc(st_ptr)
|
|
477
|
+
def copy(self):
|
|
478
|
+
"""
|
|
479
|
+
Returns a copy of the slicer.
|
|
480
|
+
"""
|
|
481
|
+
copy_ = _SlicerVineSimplicial()
|
|
482
|
+
copy_.truc = self.truc
|
|
483
|
+
return copy_
|
|
484
|
+
def get_barcode(self):
|
|
485
|
+
"""
|
|
486
|
+
Returns the current barcode.
|
|
487
|
+
"""
|
|
488
|
+
return self.truc.get_barcode()
|
|
489
|
+
def push_to_line(self, basepoint, direction=None):
|
|
490
|
+
"""
|
|
491
|
+
Pushes the current slicer to the line
|
|
492
|
+
"""
|
|
493
|
+
cdef Line[float] line
|
|
494
|
+
if direction is None:
|
|
495
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
496
|
+
else:
|
|
497
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
498
|
+
self.truc.push_to(line)
|
|
499
|
+
return self
|
|
500
|
+
|
|
501
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
502
|
+
"""
|
|
503
|
+
Computes the persistence on a line L defined by
|
|
504
|
+
- a basepoint (num_parameters,) array
|
|
505
|
+
- an optional direction (num_parameters,) array
|
|
506
|
+
"""
|
|
507
|
+
self.push_to_line(basepoint,direction)
|
|
508
|
+
self.truc.compute_persistence()
|
|
509
|
+
return self.truc.get_barcode()
|
|
510
|
+
def compute_persistence(self,one_filtration=None):
|
|
511
|
+
"""
|
|
512
|
+
Computes the current persistence, or the persistence
|
|
513
|
+
given by the filtration one_filtration (num_generators,).
|
|
514
|
+
"""
|
|
515
|
+
if one_filtration is not None:
|
|
516
|
+
self.truc.set_one_filtration(one_filtration)
|
|
517
|
+
self.truc.compute_persistence()
|
|
518
|
+
# return self.truc.get_barcode()
|
|
519
|
+
def get_barcode(self):
|
|
520
|
+
"""
|
|
521
|
+
Returns the barcode of the current 1d-persistence.
|
|
522
|
+
"""
|
|
523
|
+
return self.truc.get_barcode()
|
|
524
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
525
|
+
"""
|
|
526
|
+
Computes the filtration on a line L defined by
|
|
527
|
+
- a basepoint (num_parameters,) array
|
|
528
|
+
- an optional direction (num_parameters,) array
|
|
529
|
+
"""
|
|
530
|
+
self.push_to_line(basepoint,direction)
|
|
531
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
532
|
+
def __len__(self):
|
|
533
|
+
return self.truc.num_generators()
|
|
534
|
+
@property
|
|
535
|
+
def num_generators(self):
|
|
536
|
+
return self.truc.num_generators()
|
|
537
|
+
@property
|
|
538
|
+
def num_parameters(self):
|
|
539
|
+
return self.truc.num_parameters()
|
|
540
|
+
def info(self):
|
|
541
|
+
return self.truc.to_str().decode()
|
|
542
|
+
def compute_box(self):
|
|
543
|
+
"""
|
|
544
|
+
Computes the bounding box of the current persistence.
|
|
545
|
+
"""
|
|
546
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
547
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
548
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
549
|
+
return np.asarray([a,b])
|
|
550
|
+
def get_filtrations_values(self):
|
|
551
|
+
"""
|
|
552
|
+
Returns the current filtration values of the slicer.
|
|
553
|
+
"""
|
|
554
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
555
|
+
out = _vff21cview_f32(v, copy=True)
|
|
556
|
+
return np.asarray(out)
|
|
557
|
+
def get_filtrations(self):
|
|
558
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
559
|
+
|
|
560
|
+
def get_dimensions(self):
|
|
561
|
+
"""
|
|
562
|
+
Returns the ordered dimensions of the generators.
|
|
563
|
+
"""
|
|
564
|
+
return np.asarray(self.truc.get_dimensions())
|
|
565
|
+
def get_boundaries(self):
|
|
566
|
+
"""
|
|
567
|
+
Returns the boundaries of the generators.
|
|
568
|
+
"""
|
|
569
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
570
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
571
|
+
"""
|
|
572
|
+
Squeeze the filtration values on a grid.
|
|
573
|
+
"""
|
|
574
|
+
if force and self.is_squeezed:
|
|
575
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
576
|
+
if filtration_grid is None:
|
|
577
|
+
filtration_grid = mpg.compute_grid(
|
|
578
|
+
self.get_filtrations_values().T,
|
|
579
|
+
strategy=grid_strategy,
|
|
580
|
+
resolution=resolution)
|
|
581
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
582
|
+
if inplace or not coordinates:
|
|
583
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
584
|
+
self.filtration_grid = filtration_grid
|
|
585
|
+
else:
|
|
586
|
+
raise ValueError("WIP")
|
|
587
|
+
return self
|
|
588
|
+
def minpres(self,
|
|
589
|
+
int degree = 1,
|
|
590
|
+
list[int] degrees=[],
|
|
591
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
592
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
593
|
+
bool vineyard=True,
|
|
594
|
+
id :Optional[str] = None,
|
|
595
|
+
dtype = np.float32,
|
|
596
|
+
**minpres_kwargs
|
|
597
|
+
):
|
|
598
|
+
"""
|
|
599
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
600
|
+
"""
|
|
601
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
602
|
+
return new_slicer
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def dtype(self)->type:
|
|
606
|
+
return np.float32
|
|
607
|
+
@property
|
|
608
|
+
def col_type(self)->str:
|
|
609
|
+
return ""
|
|
610
|
+
@property
|
|
611
|
+
def is_vine(self)->bool:
|
|
612
|
+
return True
|
|
613
|
+
@property
|
|
614
|
+
def is_kcritical(self)->bool:
|
|
615
|
+
return False
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def vine_update(self,basepoint,direction=None):
|
|
619
|
+
"""
|
|
620
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
621
|
+
"""
|
|
622
|
+
self.push_to_line(basepoint,direction)
|
|
623
|
+
self.truc.vineyard_update()
|
|
624
|
+
return self
|
|
625
|
+
def get_representative_cycles(self, bool update=True):
|
|
626
|
+
"""
|
|
627
|
+
Returns the representative cycles of the current barcode.
|
|
628
|
+
Recomputes the generators if update=True
|
|
629
|
+
"""
|
|
630
|
+
return self.truc.get_representative_cycles(update)
|
|
631
|
+
def get_permutation(self):
|
|
632
|
+
"""
|
|
633
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
634
|
+
"""
|
|
635
|
+
return self.truc.get_current_order()
|
|
636
|
+
|
|
637
|
+
@staticmethod
|
|
638
|
+
def from_bitmap(self):
|
|
639
|
+
raise ValueError("Not implemented.")
|
|
640
|
+
|
|
641
|
+
#------------------------------------------------------------------------------
|
|
642
|
+
cdef class _SlicerNoVineSimplicial:
|
|
643
|
+
cdef SimplicialNoVineMatrixTruc truc
|
|
644
|
+
cdef public vector[vector[double]] filtration_grid
|
|
645
|
+
@property
|
|
646
|
+
def is_squeezed(self)->bool:
|
|
647
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
648
|
+
|
|
649
|
+
def get_ptr(self):
|
|
650
|
+
"""
|
|
651
|
+
Returns a pointer to the underlying C++ slicer.
|
|
652
|
+
"""
|
|
653
|
+
return <intptr_t>(&self.truc)
|
|
654
|
+
def __init__(self, st=None):
|
|
655
|
+
"""
|
|
656
|
+
Constructs a slicer from a simplex tree.
|
|
657
|
+
"""
|
|
658
|
+
pass
|
|
659
|
+
def __cinit__(self, st=None):
|
|
660
|
+
if st is None:
|
|
661
|
+
return
|
|
662
|
+
cdef intptr_t ptr = st.thisptr
|
|
663
|
+
cdef Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]* st_ptr = <Simplex_tree_multi_interface[Finitely_critical_multi_filtration[float],float]*>(ptr)
|
|
664
|
+
self.truc = SimplicialNoVineMatrixTruc(st_ptr)
|
|
665
|
+
def copy(self):
|
|
666
|
+
"""
|
|
667
|
+
Returns a copy of the slicer.
|
|
668
|
+
"""
|
|
669
|
+
copy_ = _SlicerNoVineSimplicial()
|
|
670
|
+
copy_.truc = self.truc
|
|
671
|
+
return copy_
|
|
672
|
+
def get_barcode(self):
|
|
673
|
+
"""
|
|
674
|
+
Returns the current barcode.
|
|
675
|
+
"""
|
|
676
|
+
return self.truc.get_barcode()
|
|
677
|
+
def push_to_line(self, basepoint, direction=None):
|
|
678
|
+
"""
|
|
679
|
+
Pushes the current slicer to the line
|
|
680
|
+
"""
|
|
681
|
+
cdef Line[float] line
|
|
682
|
+
if direction is None:
|
|
683
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
684
|
+
else:
|
|
685
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
686
|
+
self.truc.push_to(line)
|
|
687
|
+
return self
|
|
688
|
+
|
|
689
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
690
|
+
"""
|
|
691
|
+
Computes the persistence on a line L defined by
|
|
692
|
+
- a basepoint (num_parameters,) array
|
|
693
|
+
- an optional direction (num_parameters,) array
|
|
694
|
+
"""
|
|
695
|
+
self.push_to_line(basepoint,direction)
|
|
696
|
+
self.truc.compute_persistence()
|
|
697
|
+
return self.truc.get_barcode()
|
|
698
|
+
def compute_persistence(self,one_filtration=None):
|
|
699
|
+
"""
|
|
700
|
+
Computes the current persistence, or the persistence
|
|
701
|
+
given by the filtration one_filtration (num_generators,).
|
|
702
|
+
"""
|
|
703
|
+
if one_filtration is not None:
|
|
704
|
+
self.truc.set_one_filtration(one_filtration)
|
|
705
|
+
self.truc.compute_persistence()
|
|
706
|
+
# return self.truc.get_barcode()
|
|
707
|
+
def get_barcode(self):
|
|
708
|
+
"""
|
|
709
|
+
Returns the barcode of the current 1d-persistence.
|
|
710
|
+
"""
|
|
711
|
+
return self.truc.get_barcode()
|
|
712
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
713
|
+
"""
|
|
714
|
+
Computes the filtration on a line L defined by
|
|
715
|
+
- a basepoint (num_parameters,) array
|
|
716
|
+
- an optional direction (num_parameters,) array
|
|
717
|
+
"""
|
|
718
|
+
self.push_to_line(basepoint,direction)
|
|
719
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
720
|
+
def __len__(self):
|
|
721
|
+
return self.truc.num_generators()
|
|
722
|
+
@property
|
|
723
|
+
def num_generators(self):
|
|
724
|
+
return self.truc.num_generators()
|
|
725
|
+
@property
|
|
726
|
+
def num_parameters(self):
|
|
727
|
+
return self.truc.num_parameters()
|
|
728
|
+
def info(self):
|
|
729
|
+
return self.truc.to_str().decode()
|
|
730
|
+
def compute_box(self):
|
|
731
|
+
"""
|
|
732
|
+
Computes the bounding box of the current persistence.
|
|
733
|
+
"""
|
|
734
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
735
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
736
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
737
|
+
return np.asarray([a,b])
|
|
738
|
+
def get_filtrations_values(self):
|
|
739
|
+
"""
|
|
740
|
+
Returns the current filtration values of the slicer.
|
|
741
|
+
"""
|
|
742
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
743
|
+
out = _vff21cview_f32(v, copy=True)
|
|
744
|
+
return np.asarray(out)
|
|
745
|
+
def get_filtrations(self):
|
|
746
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
747
|
+
|
|
748
|
+
def get_dimensions(self):
|
|
749
|
+
"""
|
|
750
|
+
Returns the ordered dimensions of the generators.
|
|
751
|
+
"""
|
|
752
|
+
return np.asarray(self.truc.get_dimensions())
|
|
753
|
+
def get_boundaries(self):
|
|
754
|
+
"""
|
|
755
|
+
Returns the boundaries of the generators.
|
|
756
|
+
"""
|
|
757
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
758
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
759
|
+
"""
|
|
760
|
+
Squeeze the filtration values on a grid.
|
|
761
|
+
"""
|
|
762
|
+
if force and self.is_squeezed:
|
|
763
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
764
|
+
if filtration_grid is None:
|
|
765
|
+
filtration_grid = mpg.compute_grid(
|
|
766
|
+
self.get_filtrations_values().T,
|
|
767
|
+
strategy=grid_strategy,
|
|
768
|
+
resolution=resolution)
|
|
769
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
770
|
+
if inplace or not coordinates:
|
|
771
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
772
|
+
self.filtration_grid = filtration_grid
|
|
773
|
+
else:
|
|
774
|
+
raise ValueError("WIP")
|
|
775
|
+
return self
|
|
776
|
+
def minpres(self,
|
|
777
|
+
int degree = 1,
|
|
778
|
+
list[int] degrees=[],
|
|
779
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
780
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
781
|
+
bool vineyard=False,
|
|
782
|
+
id :Optional[str] = None,
|
|
783
|
+
dtype = np.float32,
|
|
784
|
+
**minpres_kwargs
|
|
785
|
+
):
|
|
786
|
+
"""
|
|
787
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
788
|
+
"""
|
|
789
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
790
|
+
return new_slicer
|
|
791
|
+
|
|
792
|
+
@property
|
|
793
|
+
def dtype(self)->type:
|
|
794
|
+
return np.float32
|
|
795
|
+
@property
|
|
796
|
+
def col_type(self)->str:
|
|
797
|
+
return ""
|
|
798
|
+
@property
|
|
799
|
+
def is_vine(self)->bool:
|
|
800
|
+
return False
|
|
801
|
+
@property
|
|
802
|
+
def is_kcritical(self)->bool:
|
|
803
|
+
return False
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
@staticmethod
|
|
808
|
+
def from_bitmap(self):
|
|
809
|
+
raise ValueError("Not implemented.")
|
|
810
|
+
|
|
811
|
+
#------------------------------------------------------------------------------
|
|
812
|
+
cdef class _KSlicer0_vine_i32:
|
|
813
|
+
cdef C_KSlicer0_vine_i32 truc
|
|
814
|
+
cdef public vector[vector[double]] filtration_grid
|
|
815
|
+
@property
|
|
816
|
+
def is_squeezed(self)->bool:
|
|
817
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
818
|
+
|
|
819
|
+
def get_ptr(self):
|
|
820
|
+
"""
|
|
821
|
+
Returns a pointer to the underlying C++ slicer.
|
|
822
|
+
"""
|
|
823
|
+
return <intptr_t>(&self.truc)
|
|
824
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
825
|
+
"""
|
|
826
|
+
Constructs a slicer from
|
|
827
|
+
- scc-like blocks
|
|
828
|
+
or
|
|
829
|
+
- generator maps (Iterable of list of ints)
|
|
830
|
+
- generator dimensions (Iterable of int)
|
|
831
|
+
- filtration values (Iterable of filtration values)
|
|
832
|
+
"""
|
|
833
|
+
pass
|
|
834
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
835
|
+
"""
|
|
836
|
+
Cython constructor
|
|
837
|
+
"""
|
|
838
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
839
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
840
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
841
|
+
generator_maps,
|
|
842
|
+
inplace=False,
|
|
843
|
+
)
|
|
844
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
845
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
846
|
+
cdef vector[KCriticalFiltration[int32_t]] c_filtration_values
|
|
847
|
+
for stuff in generator_maps:
|
|
848
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
849
|
+
cdef KCriticalFiltration[int32_t] cf
|
|
850
|
+
for F in filtration_values:
|
|
851
|
+
cf.clear()
|
|
852
|
+
for f in F:
|
|
853
|
+
cf.add_point(_py21c_i32(f))
|
|
854
|
+
c_filtration_values.push_back(cf)
|
|
855
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
856
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
857
|
+
self.truc = C_KSlicer0_vine_i32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
858
|
+
def copy(self):
|
|
859
|
+
"""
|
|
860
|
+
Returns a copy of the slicer.
|
|
861
|
+
"""
|
|
862
|
+
copy_ = _KSlicer0_vine_i32()
|
|
863
|
+
copy_.truc = self.truc
|
|
864
|
+
return copy_
|
|
865
|
+
def get_barcode(self):
|
|
866
|
+
"""
|
|
867
|
+
Returns the current barcode.
|
|
868
|
+
"""
|
|
869
|
+
return self.truc.get_barcode()
|
|
870
|
+
def push_to_line(self, basepoint, direction=None):
|
|
871
|
+
"""
|
|
872
|
+
Pushes the current slicer to the line
|
|
873
|
+
"""
|
|
874
|
+
cdef Line[int32_t] line
|
|
875
|
+
if direction is None:
|
|
876
|
+
line = Line[int32_t](_py21c_i32(basepoint))
|
|
877
|
+
else:
|
|
878
|
+
line = Line[int32_t](_py21c_i32(basepoint),_py21c_i32(direction))
|
|
879
|
+
self.truc.push_to(line)
|
|
880
|
+
return self
|
|
881
|
+
|
|
882
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
883
|
+
"""
|
|
884
|
+
Computes the persistence on a line L defined by
|
|
885
|
+
- a basepoint (num_parameters,) array
|
|
886
|
+
- an optional direction (num_parameters,) array
|
|
887
|
+
"""
|
|
888
|
+
self.push_to_line(basepoint,direction)
|
|
889
|
+
self.truc.compute_persistence()
|
|
890
|
+
return self.truc.get_barcode()
|
|
891
|
+
def compute_persistence(self,one_filtration=None):
|
|
892
|
+
"""
|
|
893
|
+
Computes the current persistence, or the persistence
|
|
894
|
+
given by the filtration one_filtration (num_generators,).
|
|
895
|
+
"""
|
|
896
|
+
if one_filtration is not None:
|
|
897
|
+
self.truc.set_one_filtration(one_filtration)
|
|
898
|
+
self.truc.compute_persistence()
|
|
899
|
+
# return self.truc.get_barcode()
|
|
900
|
+
def get_barcode(self):
|
|
901
|
+
"""
|
|
902
|
+
Returns the barcode of the current 1d-persistence.
|
|
903
|
+
"""
|
|
904
|
+
return self.truc.get_barcode()
|
|
905
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
906
|
+
"""
|
|
907
|
+
Computes the filtration on a line L defined by
|
|
908
|
+
- a basepoint (num_parameters,) array
|
|
909
|
+
- an optional direction (num_parameters,) array
|
|
910
|
+
"""
|
|
911
|
+
self.push_to_line(basepoint,direction)
|
|
912
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
913
|
+
def __len__(self):
|
|
914
|
+
return self.truc.num_generators()
|
|
915
|
+
@property
|
|
916
|
+
def num_generators(self):
|
|
917
|
+
return self.truc.num_generators()
|
|
918
|
+
@property
|
|
919
|
+
def num_parameters(self):
|
|
920
|
+
return self.truc.num_parameters()
|
|
921
|
+
def info(self):
|
|
922
|
+
return self.truc.to_str().decode()
|
|
923
|
+
def compute_box(self):
|
|
924
|
+
"""
|
|
925
|
+
Computes the bounding box of the current persistence.
|
|
926
|
+
"""
|
|
927
|
+
cdef pair[Finitely_critical_multi_filtration[int32_t],Finitely_critical_multi_filtration[int32_t]] box = self.truc.get_bounding_box()
|
|
928
|
+
cdef cnp.ndarray[int32_t, ndim=1] a = _ff21cview_i32(&box.first)
|
|
929
|
+
cdef cnp.ndarray[int32_t, ndim=1] b = _ff21cview_i32(&box.second)
|
|
930
|
+
return np.asarray([a,b])
|
|
931
|
+
def get_filtrations_values(self):
|
|
932
|
+
"""
|
|
933
|
+
Returns the current filtration values of the slicer.
|
|
934
|
+
"""
|
|
935
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] v = self.truc.get_filtration_values()
|
|
936
|
+
out = _vff21cview_i32(v, copy=True)
|
|
937
|
+
return np.asarray(out)
|
|
938
|
+
def get_filtrations(self):
|
|
939
|
+
return _vff2kcview_i32(self.truc.get_filtrations(), copy=True)
|
|
940
|
+
|
|
941
|
+
def get_dimensions(self):
|
|
942
|
+
"""
|
|
943
|
+
Returns the ordered dimensions of the generators.
|
|
944
|
+
"""
|
|
945
|
+
return np.asarray(self.truc.get_dimensions())
|
|
946
|
+
def get_boundaries(self):
|
|
947
|
+
"""
|
|
948
|
+
Returns the boundaries of the generators.
|
|
949
|
+
"""
|
|
950
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
951
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
952
|
+
"""
|
|
953
|
+
Squeeze the filtration values on a grid.
|
|
954
|
+
"""
|
|
955
|
+
if force and self.is_squeezed:
|
|
956
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
957
|
+
if filtration_grid is None:
|
|
958
|
+
filtration_grid = mpg.compute_grid(
|
|
959
|
+
self.get_filtrations_values().T,
|
|
960
|
+
strategy=grid_strategy,
|
|
961
|
+
resolution=resolution)
|
|
962
|
+
cdef vector[vector[int32_t]] grid = filtration_grid
|
|
963
|
+
if inplace or not coordinates:
|
|
964
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
965
|
+
self.filtration_grid = filtration_grid
|
|
966
|
+
else:
|
|
967
|
+
out = _KSlicer0_vine_i32()
|
|
968
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
969
|
+
out.filtration_grid = filtration_grid
|
|
970
|
+
return out
|
|
971
|
+
return self
|
|
972
|
+
def minpres(self,
|
|
973
|
+
int degree = 1,
|
|
974
|
+
list[int] degrees=[],
|
|
975
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
976
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
977
|
+
bool vineyard=True,
|
|
978
|
+
id :Optional[str] = None,
|
|
979
|
+
dtype = np.int32,
|
|
980
|
+
**minpres_kwargs
|
|
981
|
+
):
|
|
982
|
+
"""
|
|
983
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
984
|
+
"""
|
|
985
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
986
|
+
return new_slicer
|
|
987
|
+
|
|
988
|
+
@property
|
|
989
|
+
def dtype(self)->type:
|
|
990
|
+
return np.int32
|
|
991
|
+
@property
|
|
992
|
+
def col_type(self)->str:
|
|
993
|
+
return "INTRUSIVE_SET"
|
|
994
|
+
@property
|
|
995
|
+
def is_vine(self)->bool:
|
|
996
|
+
return True
|
|
997
|
+
@property
|
|
998
|
+
def is_kcritical(self)->bool:
|
|
999
|
+
return True
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
def vine_update(self,basepoint,direction=None):
|
|
1003
|
+
"""
|
|
1004
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
1005
|
+
"""
|
|
1006
|
+
self.push_to_line(basepoint,direction)
|
|
1007
|
+
self.truc.vineyard_update()
|
|
1008
|
+
return self
|
|
1009
|
+
def get_representative_cycles(self, bool update=True):
|
|
1010
|
+
"""
|
|
1011
|
+
Returns the representative cycles of the current barcode.
|
|
1012
|
+
Recomputes the generators if update=True
|
|
1013
|
+
"""
|
|
1014
|
+
return self.truc.get_representative_cycles(update)
|
|
1015
|
+
def get_permutation(self):
|
|
1016
|
+
"""
|
|
1017
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
1018
|
+
"""
|
|
1019
|
+
return self.truc.get_current_order()
|
|
1020
|
+
|
|
1021
|
+
@staticmethod
|
|
1022
|
+
def from_bitmap(self):
|
|
1023
|
+
raise ValueError("Not implemented.")
|
|
1024
|
+
|
|
1025
|
+
#------------------------------------------------------------------------------
|
|
1026
|
+
cdef class _KSlicer0_vine_f32:
|
|
1027
|
+
cdef C_KSlicer0_vine_f32 truc
|
|
1028
|
+
cdef public vector[vector[double]] filtration_grid
|
|
1029
|
+
@property
|
|
1030
|
+
def is_squeezed(self)->bool:
|
|
1031
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
1032
|
+
|
|
1033
|
+
def get_ptr(self):
|
|
1034
|
+
"""
|
|
1035
|
+
Returns a pointer to the underlying C++ slicer.
|
|
1036
|
+
"""
|
|
1037
|
+
return <intptr_t>(&self.truc)
|
|
1038
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1039
|
+
"""
|
|
1040
|
+
Constructs a slicer from
|
|
1041
|
+
- scc-like blocks
|
|
1042
|
+
or
|
|
1043
|
+
- generator maps (Iterable of list of ints)
|
|
1044
|
+
- generator dimensions (Iterable of int)
|
|
1045
|
+
- filtration values (Iterable of filtration values)
|
|
1046
|
+
"""
|
|
1047
|
+
pass
|
|
1048
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1049
|
+
"""
|
|
1050
|
+
Cython constructor
|
|
1051
|
+
"""
|
|
1052
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
1053
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
1054
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
1055
|
+
generator_maps,
|
|
1056
|
+
inplace=False,
|
|
1057
|
+
)
|
|
1058
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
1059
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
1060
|
+
cdef vector[KCriticalFiltration[float]] c_filtration_values
|
|
1061
|
+
for stuff in generator_maps:
|
|
1062
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
1063
|
+
cdef KCriticalFiltration[float] cf
|
|
1064
|
+
for F in filtration_values:
|
|
1065
|
+
cf.clear()
|
|
1066
|
+
for f in F:
|
|
1067
|
+
cf.add_point(_py21c_f32(f))
|
|
1068
|
+
c_filtration_values.push_back(cf)
|
|
1069
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
1070
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
1071
|
+
self.truc = C_KSlicer0_vine_f32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
1072
|
+
def copy(self):
|
|
1073
|
+
"""
|
|
1074
|
+
Returns a copy of the slicer.
|
|
1075
|
+
"""
|
|
1076
|
+
copy_ = _KSlicer0_vine_f32()
|
|
1077
|
+
copy_.truc = self.truc
|
|
1078
|
+
return copy_
|
|
1079
|
+
def get_barcode(self):
|
|
1080
|
+
"""
|
|
1081
|
+
Returns the current barcode.
|
|
1082
|
+
"""
|
|
1083
|
+
return self.truc.get_barcode()
|
|
1084
|
+
def push_to_line(self, basepoint, direction=None):
|
|
1085
|
+
"""
|
|
1086
|
+
Pushes the current slicer to the line
|
|
1087
|
+
"""
|
|
1088
|
+
cdef Line[float] line
|
|
1089
|
+
if direction is None:
|
|
1090
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
1091
|
+
else:
|
|
1092
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
1093
|
+
self.truc.push_to(line)
|
|
1094
|
+
return self
|
|
1095
|
+
|
|
1096
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
1097
|
+
"""
|
|
1098
|
+
Computes the persistence on a line L defined by
|
|
1099
|
+
- a basepoint (num_parameters,) array
|
|
1100
|
+
- an optional direction (num_parameters,) array
|
|
1101
|
+
"""
|
|
1102
|
+
self.push_to_line(basepoint,direction)
|
|
1103
|
+
self.truc.compute_persistence()
|
|
1104
|
+
return self.truc.get_barcode()
|
|
1105
|
+
def compute_persistence(self,one_filtration=None):
|
|
1106
|
+
"""
|
|
1107
|
+
Computes the current persistence, or the persistence
|
|
1108
|
+
given by the filtration one_filtration (num_generators,).
|
|
1109
|
+
"""
|
|
1110
|
+
if one_filtration is not None:
|
|
1111
|
+
self.truc.set_one_filtration(one_filtration)
|
|
1112
|
+
self.truc.compute_persistence()
|
|
1113
|
+
# return self.truc.get_barcode()
|
|
1114
|
+
def get_barcode(self):
|
|
1115
|
+
"""
|
|
1116
|
+
Returns the barcode of the current 1d-persistence.
|
|
1117
|
+
"""
|
|
1118
|
+
return self.truc.get_barcode()
|
|
1119
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
1120
|
+
"""
|
|
1121
|
+
Computes the filtration on a line L defined by
|
|
1122
|
+
- a basepoint (num_parameters,) array
|
|
1123
|
+
- an optional direction (num_parameters,) array
|
|
1124
|
+
"""
|
|
1125
|
+
self.push_to_line(basepoint,direction)
|
|
1126
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
1127
|
+
def __len__(self):
|
|
1128
|
+
return self.truc.num_generators()
|
|
1129
|
+
@property
|
|
1130
|
+
def num_generators(self):
|
|
1131
|
+
return self.truc.num_generators()
|
|
1132
|
+
@property
|
|
1133
|
+
def num_parameters(self):
|
|
1134
|
+
return self.truc.num_parameters()
|
|
1135
|
+
def info(self):
|
|
1136
|
+
return self.truc.to_str().decode()
|
|
1137
|
+
def compute_box(self):
|
|
1138
|
+
"""
|
|
1139
|
+
Computes the bounding box of the current persistence.
|
|
1140
|
+
"""
|
|
1141
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
1142
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
1143
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
1144
|
+
return np.asarray([a,b])
|
|
1145
|
+
def get_filtrations_values(self):
|
|
1146
|
+
"""
|
|
1147
|
+
Returns the current filtration values of the slicer.
|
|
1148
|
+
"""
|
|
1149
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
1150
|
+
out = _vff21cview_f32(v, copy=True)
|
|
1151
|
+
return np.asarray(out)
|
|
1152
|
+
def get_filtrations(self):
|
|
1153
|
+
return _vff2kcview_f32(self.truc.get_filtrations(), copy=True)
|
|
1154
|
+
|
|
1155
|
+
def get_dimensions(self):
|
|
1156
|
+
"""
|
|
1157
|
+
Returns the ordered dimensions of the generators.
|
|
1158
|
+
"""
|
|
1159
|
+
return np.asarray(self.truc.get_dimensions())
|
|
1160
|
+
def get_boundaries(self):
|
|
1161
|
+
"""
|
|
1162
|
+
Returns the boundaries of the generators.
|
|
1163
|
+
"""
|
|
1164
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
1165
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
1166
|
+
"""
|
|
1167
|
+
Squeeze the filtration values on a grid.
|
|
1168
|
+
"""
|
|
1169
|
+
if force and self.is_squeezed:
|
|
1170
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
1171
|
+
if filtration_grid is None:
|
|
1172
|
+
filtration_grid = mpg.compute_grid(
|
|
1173
|
+
self.get_filtrations_values().T,
|
|
1174
|
+
strategy=grid_strategy,
|
|
1175
|
+
resolution=resolution)
|
|
1176
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
1177
|
+
if inplace or not coordinates:
|
|
1178
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
1179
|
+
self.filtration_grid = filtration_grid
|
|
1180
|
+
else:
|
|
1181
|
+
out = _KSlicer0_vine_i32()
|
|
1182
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
1183
|
+
out.filtration_grid = filtration_grid
|
|
1184
|
+
return out
|
|
1185
|
+
return self
|
|
1186
|
+
def minpres(self,
|
|
1187
|
+
int degree = 1,
|
|
1188
|
+
list[int] degrees=[],
|
|
1189
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
1190
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
1191
|
+
bool vineyard=True,
|
|
1192
|
+
id :Optional[str] = None,
|
|
1193
|
+
dtype = np.float32,
|
|
1194
|
+
**minpres_kwargs
|
|
1195
|
+
):
|
|
1196
|
+
"""
|
|
1197
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
1198
|
+
"""
|
|
1199
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
1200
|
+
return new_slicer
|
|
1201
|
+
|
|
1202
|
+
@property
|
|
1203
|
+
def dtype(self)->type:
|
|
1204
|
+
return np.float32
|
|
1205
|
+
@property
|
|
1206
|
+
def col_type(self)->str:
|
|
1207
|
+
return "INTRUSIVE_SET"
|
|
1208
|
+
@property
|
|
1209
|
+
def is_vine(self)->bool:
|
|
1210
|
+
return True
|
|
1211
|
+
@property
|
|
1212
|
+
def is_kcritical(self)->bool:
|
|
1213
|
+
return True
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
def vine_update(self,basepoint,direction=None):
|
|
1217
|
+
"""
|
|
1218
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
1219
|
+
"""
|
|
1220
|
+
self.push_to_line(basepoint,direction)
|
|
1221
|
+
self.truc.vineyard_update()
|
|
1222
|
+
return self
|
|
1223
|
+
def get_representative_cycles(self, bool update=True):
|
|
1224
|
+
"""
|
|
1225
|
+
Returns the representative cycles of the current barcode.
|
|
1226
|
+
Recomputes the generators if update=True
|
|
1227
|
+
"""
|
|
1228
|
+
return self.truc.get_representative_cycles(update)
|
|
1229
|
+
def get_permutation(self):
|
|
1230
|
+
"""
|
|
1231
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
1232
|
+
"""
|
|
1233
|
+
return self.truc.get_current_order()
|
|
1234
|
+
|
|
1235
|
+
@staticmethod
|
|
1236
|
+
def from_bitmap(self):
|
|
1237
|
+
raise ValueError("Not implemented.")
|
|
1238
|
+
|
|
1239
|
+
#------------------------------------------------------------------------------
|
|
1240
|
+
cdef class _KSlicer0_vine_f64:
|
|
1241
|
+
cdef C_KSlicer0_vine_f64 truc
|
|
1242
|
+
cdef public vector[vector[double]] filtration_grid
|
|
1243
|
+
@property
|
|
1244
|
+
def is_squeezed(self)->bool:
|
|
1245
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
1246
|
+
|
|
1247
|
+
def get_ptr(self):
|
|
1248
|
+
"""
|
|
1249
|
+
Returns a pointer to the underlying C++ slicer.
|
|
1250
|
+
"""
|
|
1251
|
+
return <intptr_t>(&self.truc)
|
|
1252
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1253
|
+
"""
|
|
1254
|
+
Constructs a slicer from
|
|
1255
|
+
- scc-like blocks
|
|
1256
|
+
or
|
|
1257
|
+
- generator maps (Iterable of list of ints)
|
|
1258
|
+
- generator dimensions (Iterable of int)
|
|
1259
|
+
- filtration values (Iterable of filtration values)
|
|
1260
|
+
"""
|
|
1261
|
+
pass
|
|
1262
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1263
|
+
"""
|
|
1264
|
+
Cython constructor
|
|
1265
|
+
"""
|
|
1266
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
1267
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
1268
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
1269
|
+
generator_maps,
|
|
1270
|
+
inplace=False,
|
|
1271
|
+
)
|
|
1272
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
1273
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
1274
|
+
cdef vector[KCriticalFiltration[double]] c_filtration_values
|
|
1275
|
+
for stuff in generator_maps:
|
|
1276
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
1277
|
+
cdef KCriticalFiltration[double] cf
|
|
1278
|
+
for F in filtration_values:
|
|
1279
|
+
cf.clear()
|
|
1280
|
+
for f in F:
|
|
1281
|
+
cf.add_point(_py21c_f64(f))
|
|
1282
|
+
c_filtration_values.push_back(cf)
|
|
1283
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
1284
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
1285
|
+
self.truc = C_KSlicer0_vine_f64(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
1286
|
+
def copy(self):
|
|
1287
|
+
"""
|
|
1288
|
+
Returns a copy of the slicer.
|
|
1289
|
+
"""
|
|
1290
|
+
copy_ = _KSlicer0_vine_f64()
|
|
1291
|
+
copy_.truc = self.truc
|
|
1292
|
+
return copy_
|
|
1293
|
+
def get_barcode(self):
|
|
1294
|
+
"""
|
|
1295
|
+
Returns the current barcode.
|
|
1296
|
+
"""
|
|
1297
|
+
return self.truc.get_barcode()
|
|
1298
|
+
def push_to_line(self, basepoint, direction=None):
|
|
1299
|
+
"""
|
|
1300
|
+
Pushes the current slicer to the line
|
|
1301
|
+
"""
|
|
1302
|
+
cdef Line[double] line
|
|
1303
|
+
if direction is None:
|
|
1304
|
+
line = Line[double](_py21c_f64(basepoint))
|
|
1305
|
+
else:
|
|
1306
|
+
line = Line[double](_py21c_f64(basepoint),_py21c_f64(direction))
|
|
1307
|
+
self.truc.push_to(line)
|
|
1308
|
+
return self
|
|
1309
|
+
|
|
1310
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
1311
|
+
"""
|
|
1312
|
+
Computes the persistence on a line L defined by
|
|
1313
|
+
- a basepoint (num_parameters,) array
|
|
1314
|
+
- an optional direction (num_parameters,) array
|
|
1315
|
+
"""
|
|
1316
|
+
self.push_to_line(basepoint,direction)
|
|
1317
|
+
self.truc.compute_persistence()
|
|
1318
|
+
return self.truc.get_barcode()
|
|
1319
|
+
def compute_persistence(self,one_filtration=None):
|
|
1320
|
+
"""
|
|
1321
|
+
Computes the current persistence, or the persistence
|
|
1322
|
+
given by the filtration one_filtration (num_generators,).
|
|
1323
|
+
"""
|
|
1324
|
+
if one_filtration is not None:
|
|
1325
|
+
self.truc.set_one_filtration(one_filtration)
|
|
1326
|
+
self.truc.compute_persistence()
|
|
1327
|
+
# return self.truc.get_barcode()
|
|
1328
|
+
def get_barcode(self):
|
|
1329
|
+
"""
|
|
1330
|
+
Returns the barcode of the current 1d-persistence.
|
|
1331
|
+
"""
|
|
1332
|
+
return self.truc.get_barcode()
|
|
1333
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
1334
|
+
"""
|
|
1335
|
+
Computes the filtration on a line L defined by
|
|
1336
|
+
- a basepoint (num_parameters,) array
|
|
1337
|
+
- an optional direction (num_parameters,) array
|
|
1338
|
+
"""
|
|
1339
|
+
self.push_to_line(basepoint,direction)
|
|
1340
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
1341
|
+
def __len__(self):
|
|
1342
|
+
return self.truc.num_generators()
|
|
1343
|
+
@property
|
|
1344
|
+
def num_generators(self):
|
|
1345
|
+
return self.truc.num_generators()
|
|
1346
|
+
@property
|
|
1347
|
+
def num_parameters(self):
|
|
1348
|
+
return self.truc.num_parameters()
|
|
1349
|
+
def info(self):
|
|
1350
|
+
return self.truc.to_str().decode()
|
|
1351
|
+
def compute_box(self):
|
|
1352
|
+
"""
|
|
1353
|
+
Computes the bounding box of the current persistence.
|
|
1354
|
+
"""
|
|
1355
|
+
cdef pair[Finitely_critical_multi_filtration[double],Finitely_critical_multi_filtration[double]] box = self.truc.get_bounding_box()
|
|
1356
|
+
cdef cnp.ndarray[double, ndim=1] a = _ff21cview_f64(&box.first)
|
|
1357
|
+
cdef cnp.ndarray[double, ndim=1] b = _ff21cview_f64(&box.second)
|
|
1358
|
+
return np.asarray([a,b])
|
|
1359
|
+
def get_filtrations_values(self):
|
|
1360
|
+
"""
|
|
1361
|
+
Returns the current filtration values of the slicer.
|
|
1362
|
+
"""
|
|
1363
|
+
cdef vector[Finitely_critical_multi_filtration[double]] v = self.truc.get_filtration_values()
|
|
1364
|
+
out = _vff21cview_f64(v, copy=True)
|
|
1365
|
+
return np.asarray(out)
|
|
1366
|
+
def get_filtrations(self):
|
|
1367
|
+
return _vff2kcview_f64(self.truc.get_filtrations(), copy=True)
|
|
1368
|
+
|
|
1369
|
+
def get_dimensions(self):
|
|
1370
|
+
"""
|
|
1371
|
+
Returns the ordered dimensions of the generators.
|
|
1372
|
+
"""
|
|
1373
|
+
return np.asarray(self.truc.get_dimensions())
|
|
1374
|
+
def get_boundaries(self):
|
|
1375
|
+
"""
|
|
1376
|
+
Returns the boundaries of the generators.
|
|
1377
|
+
"""
|
|
1378
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
1379
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
1380
|
+
"""
|
|
1381
|
+
Squeeze the filtration values on a grid.
|
|
1382
|
+
"""
|
|
1383
|
+
if force and self.is_squeezed:
|
|
1384
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
1385
|
+
if filtration_grid is None:
|
|
1386
|
+
filtration_grid = mpg.compute_grid(
|
|
1387
|
+
self.get_filtrations_values().T,
|
|
1388
|
+
strategy=grid_strategy,
|
|
1389
|
+
resolution=resolution)
|
|
1390
|
+
cdef vector[vector[double]] grid = filtration_grid
|
|
1391
|
+
if inplace or not coordinates:
|
|
1392
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
1393
|
+
self.filtration_grid = filtration_grid
|
|
1394
|
+
else:
|
|
1395
|
+
out = _KSlicer0_vine_i32()
|
|
1396
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
1397
|
+
out.filtration_grid = filtration_grid
|
|
1398
|
+
return out
|
|
1399
|
+
return self
|
|
1400
|
+
def minpres(self,
|
|
1401
|
+
int degree = 1,
|
|
1402
|
+
list[int] degrees=[],
|
|
1403
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
1404
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
1405
|
+
bool vineyard=True,
|
|
1406
|
+
id :Optional[str] = None,
|
|
1407
|
+
dtype = np.float64,
|
|
1408
|
+
**minpres_kwargs
|
|
1409
|
+
):
|
|
1410
|
+
"""
|
|
1411
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
1412
|
+
"""
|
|
1413
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
1414
|
+
return new_slicer
|
|
1415
|
+
|
|
1416
|
+
@property
|
|
1417
|
+
def dtype(self)->type:
|
|
1418
|
+
return np.float64
|
|
1419
|
+
@property
|
|
1420
|
+
def col_type(self)->str:
|
|
1421
|
+
return "INTRUSIVE_SET"
|
|
1422
|
+
@property
|
|
1423
|
+
def is_vine(self)->bool:
|
|
1424
|
+
return True
|
|
1425
|
+
@property
|
|
1426
|
+
def is_kcritical(self)->bool:
|
|
1427
|
+
return True
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
def vine_update(self,basepoint,direction=None):
|
|
1431
|
+
"""
|
|
1432
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
1433
|
+
"""
|
|
1434
|
+
self.push_to_line(basepoint,direction)
|
|
1435
|
+
self.truc.vineyard_update()
|
|
1436
|
+
return self
|
|
1437
|
+
def get_representative_cycles(self, bool update=True):
|
|
1438
|
+
"""
|
|
1439
|
+
Returns the representative cycles of the current barcode.
|
|
1440
|
+
Recomputes the generators if update=True
|
|
1441
|
+
"""
|
|
1442
|
+
return self.truc.get_representative_cycles(update)
|
|
1443
|
+
def get_permutation(self):
|
|
1444
|
+
"""
|
|
1445
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
1446
|
+
"""
|
|
1447
|
+
return self.truc.get_current_order()
|
|
1448
|
+
|
|
1449
|
+
@staticmethod
|
|
1450
|
+
def from_bitmap(self):
|
|
1451
|
+
raise ValueError("Not implemented.")
|
|
1452
|
+
|
|
1453
|
+
#------------------------------------------------------------------------------
|
|
1454
|
+
cdef class _Slicer0_vine_i32:
|
|
1455
|
+
cdef C_Slicer0_vine_i32 truc
|
|
1456
|
+
cdef public vector[vector[double]] filtration_grid
|
|
1457
|
+
@property
|
|
1458
|
+
def is_squeezed(self)->bool:
|
|
1459
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
1460
|
+
|
|
1461
|
+
def get_ptr(self):
|
|
1462
|
+
"""
|
|
1463
|
+
Returns a pointer to the underlying C++ slicer.
|
|
1464
|
+
"""
|
|
1465
|
+
return <intptr_t>(&self.truc)
|
|
1466
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1467
|
+
"""
|
|
1468
|
+
Constructs a slicer from
|
|
1469
|
+
- generator maps (Iterable of list of ints)
|
|
1470
|
+
- generator dimensions (Iterable of int)
|
|
1471
|
+
- filtration values (Iterable of filtration values)
|
|
1472
|
+
"""
|
|
1473
|
+
pass
|
|
1474
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1475
|
+
"""
|
|
1476
|
+
Cython constructor
|
|
1477
|
+
"""
|
|
1478
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
1479
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
1480
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] c_filtration_values
|
|
1481
|
+
for stuff in generator_maps:
|
|
1482
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
1483
|
+
for f in filtration_values:
|
|
1484
|
+
# cf.clear()
|
|
1485
|
+
# for truc in f:
|
|
1486
|
+
# cf.push_back(truc)
|
|
1487
|
+
c_filtration_values.push_back(_py21c_i32(f))
|
|
1488
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
1489
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
1490
|
+
self.truc = C_Slicer0_vine_i32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
1491
|
+
def copy(self):
|
|
1492
|
+
"""
|
|
1493
|
+
Returns a copy of the slicer.
|
|
1494
|
+
"""
|
|
1495
|
+
copy_ = _Slicer0_vine_i32()
|
|
1496
|
+
copy_.truc = self.truc
|
|
1497
|
+
return copy_
|
|
1498
|
+
def get_barcode(self):
|
|
1499
|
+
"""
|
|
1500
|
+
Returns the current barcode.
|
|
1501
|
+
"""
|
|
1502
|
+
return self.truc.get_barcode()
|
|
1503
|
+
def push_to_line(self, basepoint, direction=None):
|
|
1504
|
+
"""
|
|
1505
|
+
Pushes the current slicer to the line
|
|
1506
|
+
"""
|
|
1507
|
+
cdef Line[int32_t] line
|
|
1508
|
+
if direction is None:
|
|
1509
|
+
line = Line[int32_t](_py21c_i32(basepoint))
|
|
1510
|
+
else:
|
|
1511
|
+
line = Line[int32_t](_py21c_i32(basepoint),_py21c_i32(direction))
|
|
1512
|
+
self.truc.push_to(line)
|
|
1513
|
+
return self
|
|
1514
|
+
|
|
1515
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
1516
|
+
"""
|
|
1517
|
+
Computes the persistence on a line L defined by
|
|
1518
|
+
- a basepoint (num_parameters,) array
|
|
1519
|
+
- an optional direction (num_parameters,) array
|
|
1520
|
+
"""
|
|
1521
|
+
self.push_to_line(basepoint,direction)
|
|
1522
|
+
self.truc.compute_persistence()
|
|
1523
|
+
return self.truc.get_barcode()
|
|
1524
|
+
def compute_persistence(self,one_filtration=None):
|
|
1525
|
+
"""
|
|
1526
|
+
Computes the current persistence, or the persistence
|
|
1527
|
+
given by the filtration one_filtration (num_generators,).
|
|
1528
|
+
"""
|
|
1529
|
+
if one_filtration is not None:
|
|
1530
|
+
self.truc.set_one_filtration(one_filtration)
|
|
1531
|
+
self.truc.compute_persistence()
|
|
1532
|
+
# return self.truc.get_barcode()
|
|
1533
|
+
def get_barcode(self):
|
|
1534
|
+
"""
|
|
1535
|
+
Returns the barcode of the current 1d-persistence.
|
|
1536
|
+
"""
|
|
1537
|
+
return self.truc.get_barcode()
|
|
1538
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
1539
|
+
"""
|
|
1540
|
+
Computes the filtration on a line L defined by
|
|
1541
|
+
- a basepoint (num_parameters,) array
|
|
1542
|
+
- an optional direction (num_parameters,) array
|
|
1543
|
+
"""
|
|
1544
|
+
self.push_to_line(basepoint,direction)
|
|
1545
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
1546
|
+
def __len__(self):
|
|
1547
|
+
return self.truc.num_generators()
|
|
1548
|
+
@property
|
|
1549
|
+
def num_generators(self):
|
|
1550
|
+
return self.truc.num_generators()
|
|
1551
|
+
@property
|
|
1552
|
+
def num_parameters(self):
|
|
1553
|
+
return self.truc.num_parameters()
|
|
1554
|
+
def info(self):
|
|
1555
|
+
return self.truc.to_str().decode()
|
|
1556
|
+
def compute_box(self):
|
|
1557
|
+
"""
|
|
1558
|
+
Computes the bounding box of the current persistence.
|
|
1559
|
+
"""
|
|
1560
|
+
cdef pair[Finitely_critical_multi_filtration[int32_t],Finitely_critical_multi_filtration[int32_t]] box = self.truc.get_bounding_box()
|
|
1561
|
+
cdef cnp.ndarray[int32_t, ndim=1] a = _ff21cview_i32(&box.first)
|
|
1562
|
+
cdef cnp.ndarray[int32_t, ndim=1] b = _ff21cview_i32(&box.second)
|
|
1563
|
+
return np.asarray([a,b])
|
|
1564
|
+
def get_filtrations_values(self):
|
|
1565
|
+
"""
|
|
1566
|
+
Returns the current filtration values of the slicer.
|
|
1567
|
+
"""
|
|
1568
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] v = self.truc.get_filtration_values()
|
|
1569
|
+
out = _vff21cview_i32(v, copy=True)
|
|
1570
|
+
return np.asarray(out)
|
|
1571
|
+
def get_filtrations(self):
|
|
1572
|
+
return _vff21cview_i32(self.truc.get_filtrations(), copy=True)
|
|
1573
|
+
|
|
1574
|
+
def get_dimensions(self):
|
|
1575
|
+
"""
|
|
1576
|
+
Returns the ordered dimensions of the generators.
|
|
1577
|
+
"""
|
|
1578
|
+
return np.asarray(self.truc.get_dimensions())
|
|
1579
|
+
def get_boundaries(self):
|
|
1580
|
+
"""
|
|
1581
|
+
Returns the boundaries of the generators.
|
|
1582
|
+
"""
|
|
1583
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
1584
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
1585
|
+
"""
|
|
1586
|
+
Squeeze the filtration values on a grid.
|
|
1587
|
+
"""
|
|
1588
|
+
if force and self.is_squeezed:
|
|
1589
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
1590
|
+
if filtration_grid is None:
|
|
1591
|
+
filtration_grid = mpg.compute_grid(
|
|
1592
|
+
self.get_filtrations_values().T,
|
|
1593
|
+
strategy=grid_strategy,
|
|
1594
|
+
resolution=resolution)
|
|
1595
|
+
cdef vector[vector[int32_t]] grid = filtration_grid
|
|
1596
|
+
if inplace or not coordinates:
|
|
1597
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
1598
|
+
self.filtration_grid = filtration_grid
|
|
1599
|
+
else:
|
|
1600
|
+
out = _Slicer0_vine_i32()
|
|
1601
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
1602
|
+
out.filtration_grid = filtration_grid
|
|
1603
|
+
return out
|
|
1604
|
+
return self
|
|
1605
|
+
def minpres(self,
|
|
1606
|
+
int degree = 1,
|
|
1607
|
+
list[int] degrees=[],
|
|
1608
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
1609
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
1610
|
+
bool vineyard=True,
|
|
1611
|
+
id :Optional[str] = None,
|
|
1612
|
+
dtype = np.int32,
|
|
1613
|
+
**minpres_kwargs
|
|
1614
|
+
):
|
|
1615
|
+
"""
|
|
1616
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
1617
|
+
"""
|
|
1618
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
1619
|
+
return new_slicer
|
|
1620
|
+
|
|
1621
|
+
@property
|
|
1622
|
+
def dtype(self)->type:
|
|
1623
|
+
return np.int32
|
|
1624
|
+
@property
|
|
1625
|
+
def col_type(self)->str:
|
|
1626
|
+
return "INTRUSIVE_SET"
|
|
1627
|
+
@property
|
|
1628
|
+
def is_vine(self)->bool:
|
|
1629
|
+
return True
|
|
1630
|
+
@property
|
|
1631
|
+
def is_kcritical(self)->bool:
|
|
1632
|
+
return False
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
def vine_update(self,basepoint,direction=None):
|
|
1636
|
+
"""
|
|
1637
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
1638
|
+
"""
|
|
1639
|
+
self.push_to_line(basepoint,direction)
|
|
1640
|
+
self.truc.vineyard_update()
|
|
1641
|
+
return self
|
|
1642
|
+
def get_representative_cycles(self, bool update=True):
|
|
1643
|
+
"""
|
|
1644
|
+
Returns the representative cycles of the current barcode.
|
|
1645
|
+
Recomputes the generators if update=True
|
|
1646
|
+
"""
|
|
1647
|
+
return self.truc.get_representative_cycles(update)
|
|
1648
|
+
def get_permutation(self):
|
|
1649
|
+
"""
|
|
1650
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
1651
|
+
"""
|
|
1652
|
+
return self.truc.get_current_order()
|
|
1653
|
+
|
|
1654
|
+
@staticmethod
|
|
1655
|
+
def from_bitmap(self):
|
|
1656
|
+
raise ValueError("Not implemented.")
|
|
1657
|
+
|
|
1658
|
+
#------------------------------------------------------------------------------
|
|
1659
|
+
cdef class _Slicer0_vine_f32:
|
|
1660
|
+
cdef C_Slicer0_vine_f32 truc
|
|
1661
|
+
cdef public vector[vector[double]] filtration_grid
|
|
1662
|
+
@property
|
|
1663
|
+
def is_squeezed(self)->bool:
|
|
1664
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
1665
|
+
|
|
1666
|
+
def get_ptr(self):
|
|
1667
|
+
"""
|
|
1668
|
+
Returns a pointer to the underlying C++ slicer.
|
|
1669
|
+
"""
|
|
1670
|
+
return <intptr_t>(&self.truc)
|
|
1671
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1672
|
+
"""
|
|
1673
|
+
Constructs a slicer from
|
|
1674
|
+
- generator maps (Iterable of list of ints)
|
|
1675
|
+
- generator dimensions (Iterable of int)
|
|
1676
|
+
- filtration values (Iterable of filtration values)
|
|
1677
|
+
"""
|
|
1678
|
+
pass
|
|
1679
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1680
|
+
"""
|
|
1681
|
+
Cython constructor
|
|
1682
|
+
"""
|
|
1683
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
1684
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
1685
|
+
cdef vector[Finitely_critical_multi_filtration[float]] c_filtration_values
|
|
1686
|
+
for stuff in generator_maps:
|
|
1687
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
1688
|
+
for f in filtration_values:
|
|
1689
|
+
# cf.clear()
|
|
1690
|
+
# for truc in f:
|
|
1691
|
+
# cf.push_back(truc)
|
|
1692
|
+
c_filtration_values.push_back(_py21c_f32(f))
|
|
1693
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
1694
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
1695
|
+
self.truc = C_Slicer0_vine_f32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
1696
|
+
def copy(self):
|
|
1697
|
+
"""
|
|
1698
|
+
Returns a copy of the slicer.
|
|
1699
|
+
"""
|
|
1700
|
+
copy_ = _Slicer0_vine_f32()
|
|
1701
|
+
copy_.truc = self.truc
|
|
1702
|
+
return copy_
|
|
1703
|
+
def get_barcode(self):
|
|
1704
|
+
"""
|
|
1705
|
+
Returns the current barcode.
|
|
1706
|
+
"""
|
|
1707
|
+
return self.truc.get_barcode()
|
|
1708
|
+
def push_to_line(self, basepoint, direction=None):
|
|
1709
|
+
"""
|
|
1710
|
+
Pushes the current slicer to the line
|
|
1711
|
+
"""
|
|
1712
|
+
cdef Line[float] line
|
|
1713
|
+
if direction is None:
|
|
1714
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
1715
|
+
else:
|
|
1716
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
1717
|
+
self.truc.push_to(line)
|
|
1718
|
+
return self
|
|
1719
|
+
|
|
1720
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
1721
|
+
"""
|
|
1722
|
+
Computes the persistence on a line L defined by
|
|
1723
|
+
- a basepoint (num_parameters,) array
|
|
1724
|
+
- an optional direction (num_parameters,) array
|
|
1725
|
+
"""
|
|
1726
|
+
self.push_to_line(basepoint,direction)
|
|
1727
|
+
self.truc.compute_persistence()
|
|
1728
|
+
return self.truc.get_barcode()
|
|
1729
|
+
def compute_persistence(self,one_filtration=None):
|
|
1730
|
+
"""
|
|
1731
|
+
Computes the current persistence, or the persistence
|
|
1732
|
+
given by the filtration one_filtration (num_generators,).
|
|
1733
|
+
"""
|
|
1734
|
+
if one_filtration is not None:
|
|
1735
|
+
self.truc.set_one_filtration(one_filtration)
|
|
1736
|
+
self.truc.compute_persistence()
|
|
1737
|
+
# return self.truc.get_barcode()
|
|
1738
|
+
def get_barcode(self):
|
|
1739
|
+
"""
|
|
1740
|
+
Returns the barcode of the current 1d-persistence.
|
|
1741
|
+
"""
|
|
1742
|
+
return self.truc.get_barcode()
|
|
1743
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
1744
|
+
"""
|
|
1745
|
+
Computes the filtration on a line L defined by
|
|
1746
|
+
- a basepoint (num_parameters,) array
|
|
1747
|
+
- an optional direction (num_parameters,) array
|
|
1748
|
+
"""
|
|
1749
|
+
self.push_to_line(basepoint,direction)
|
|
1750
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
1751
|
+
def __len__(self):
|
|
1752
|
+
return self.truc.num_generators()
|
|
1753
|
+
@property
|
|
1754
|
+
def num_generators(self):
|
|
1755
|
+
return self.truc.num_generators()
|
|
1756
|
+
@property
|
|
1757
|
+
def num_parameters(self):
|
|
1758
|
+
return self.truc.num_parameters()
|
|
1759
|
+
def info(self):
|
|
1760
|
+
return self.truc.to_str().decode()
|
|
1761
|
+
def compute_box(self):
|
|
1762
|
+
"""
|
|
1763
|
+
Computes the bounding box of the current persistence.
|
|
1764
|
+
"""
|
|
1765
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
1766
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
1767
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
1768
|
+
return np.asarray([a,b])
|
|
1769
|
+
def get_filtrations_values(self):
|
|
1770
|
+
"""
|
|
1771
|
+
Returns the current filtration values of the slicer.
|
|
1772
|
+
"""
|
|
1773
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
1774
|
+
out = _vff21cview_f32(v, copy=True)
|
|
1775
|
+
return np.asarray(out)
|
|
1776
|
+
def get_filtrations(self):
|
|
1777
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
1778
|
+
|
|
1779
|
+
def get_dimensions(self):
|
|
1780
|
+
"""
|
|
1781
|
+
Returns the ordered dimensions of the generators.
|
|
1782
|
+
"""
|
|
1783
|
+
return np.asarray(self.truc.get_dimensions())
|
|
1784
|
+
def get_boundaries(self):
|
|
1785
|
+
"""
|
|
1786
|
+
Returns the boundaries of the generators.
|
|
1787
|
+
"""
|
|
1788
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
1789
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
1790
|
+
"""
|
|
1791
|
+
Squeeze the filtration values on a grid.
|
|
1792
|
+
"""
|
|
1793
|
+
if force and self.is_squeezed:
|
|
1794
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
1795
|
+
if filtration_grid is None:
|
|
1796
|
+
filtration_grid = mpg.compute_grid(
|
|
1797
|
+
self.get_filtrations_values().T,
|
|
1798
|
+
strategy=grid_strategy,
|
|
1799
|
+
resolution=resolution)
|
|
1800
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
1801
|
+
if inplace or not coordinates:
|
|
1802
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
1803
|
+
self.filtration_grid = filtration_grid
|
|
1804
|
+
else:
|
|
1805
|
+
out = _Slicer0_vine_i32()
|
|
1806
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
1807
|
+
out.filtration_grid = filtration_grid
|
|
1808
|
+
return out
|
|
1809
|
+
return self
|
|
1810
|
+
def minpres(self,
|
|
1811
|
+
int degree = 1,
|
|
1812
|
+
list[int] degrees=[],
|
|
1813
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
1814
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
1815
|
+
bool vineyard=True,
|
|
1816
|
+
id :Optional[str] = None,
|
|
1817
|
+
dtype = np.float32,
|
|
1818
|
+
**minpres_kwargs
|
|
1819
|
+
):
|
|
1820
|
+
"""
|
|
1821
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
1822
|
+
"""
|
|
1823
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
1824
|
+
return new_slicer
|
|
1825
|
+
|
|
1826
|
+
@property
|
|
1827
|
+
def dtype(self)->type:
|
|
1828
|
+
return np.float32
|
|
1829
|
+
@property
|
|
1830
|
+
def col_type(self)->str:
|
|
1831
|
+
return "INTRUSIVE_SET"
|
|
1832
|
+
@property
|
|
1833
|
+
def is_vine(self)->bool:
|
|
1834
|
+
return True
|
|
1835
|
+
@property
|
|
1836
|
+
def is_kcritical(self)->bool:
|
|
1837
|
+
return False
|
|
1838
|
+
|
|
1839
|
+
|
|
1840
|
+
def vine_update(self,basepoint,direction=None):
|
|
1841
|
+
"""
|
|
1842
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
1843
|
+
"""
|
|
1844
|
+
self.push_to_line(basepoint,direction)
|
|
1845
|
+
self.truc.vineyard_update()
|
|
1846
|
+
return self
|
|
1847
|
+
def get_representative_cycles(self, bool update=True):
|
|
1848
|
+
"""
|
|
1849
|
+
Returns the representative cycles of the current barcode.
|
|
1850
|
+
Recomputes the generators if update=True
|
|
1851
|
+
"""
|
|
1852
|
+
return self.truc.get_representative_cycles(update)
|
|
1853
|
+
def get_permutation(self):
|
|
1854
|
+
"""
|
|
1855
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
1856
|
+
"""
|
|
1857
|
+
return self.truc.get_current_order()
|
|
1858
|
+
|
|
1859
|
+
@staticmethod
|
|
1860
|
+
def from_bitmap(self):
|
|
1861
|
+
raise ValueError("Not implemented.")
|
|
1862
|
+
|
|
1863
|
+
#------------------------------------------------------------------------------
|
|
1864
|
+
cdef class _Slicer0_vine_f64:
|
|
1865
|
+
cdef C_Slicer0_vine_f64 truc
|
|
1866
|
+
cdef public vector[vector[double]] filtration_grid
|
|
1867
|
+
@property
|
|
1868
|
+
def is_squeezed(self)->bool:
|
|
1869
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
1870
|
+
|
|
1871
|
+
def get_ptr(self):
|
|
1872
|
+
"""
|
|
1873
|
+
Returns a pointer to the underlying C++ slicer.
|
|
1874
|
+
"""
|
|
1875
|
+
return <intptr_t>(&self.truc)
|
|
1876
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1877
|
+
"""
|
|
1878
|
+
Constructs a slicer from
|
|
1879
|
+
- generator maps (Iterable of list of ints)
|
|
1880
|
+
- generator dimensions (Iterable of int)
|
|
1881
|
+
- filtration values (Iterable of filtration values)
|
|
1882
|
+
"""
|
|
1883
|
+
pass
|
|
1884
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
1885
|
+
"""
|
|
1886
|
+
Cython constructor
|
|
1887
|
+
"""
|
|
1888
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
1889
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
1890
|
+
cdef vector[Finitely_critical_multi_filtration[double]] c_filtration_values
|
|
1891
|
+
for stuff in generator_maps:
|
|
1892
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
1893
|
+
for f in filtration_values:
|
|
1894
|
+
# cf.clear()
|
|
1895
|
+
# for truc in f:
|
|
1896
|
+
# cf.push_back(truc)
|
|
1897
|
+
c_filtration_values.push_back(_py21c_f64(f))
|
|
1898
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
1899
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
1900
|
+
self.truc = C_Slicer0_vine_f64(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
1901
|
+
def copy(self):
|
|
1902
|
+
"""
|
|
1903
|
+
Returns a copy of the slicer.
|
|
1904
|
+
"""
|
|
1905
|
+
copy_ = _Slicer0_vine_f64()
|
|
1906
|
+
copy_.truc = self.truc
|
|
1907
|
+
return copy_
|
|
1908
|
+
def get_barcode(self):
|
|
1909
|
+
"""
|
|
1910
|
+
Returns the current barcode.
|
|
1911
|
+
"""
|
|
1912
|
+
return self.truc.get_barcode()
|
|
1913
|
+
def push_to_line(self, basepoint, direction=None):
|
|
1914
|
+
"""
|
|
1915
|
+
Pushes the current slicer to the line
|
|
1916
|
+
"""
|
|
1917
|
+
cdef Line[double] line
|
|
1918
|
+
if direction is None:
|
|
1919
|
+
line = Line[double](_py21c_f64(basepoint))
|
|
1920
|
+
else:
|
|
1921
|
+
line = Line[double](_py21c_f64(basepoint),_py21c_f64(direction))
|
|
1922
|
+
self.truc.push_to(line)
|
|
1923
|
+
return self
|
|
1924
|
+
|
|
1925
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
1926
|
+
"""
|
|
1927
|
+
Computes the persistence on a line L defined by
|
|
1928
|
+
- a basepoint (num_parameters,) array
|
|
1929
|
+
- an optional direction (num_parameters,) array
|
|
1930
|
+
"""
|
|
1931
|
+
self.push_to_line(basepoint,direction)
|
|
1932
|
+
self.truc.compute_persistence()
|
|
1933
|
+
return self.truc.get_barcode()
|
|
1934
|
+
def compute_persistence(self,one_filtration=None):
|
|
1935
|
+
"""
|
|
1936
|
+
Computes the current persistence, or the persistence
|
|
1937
|
+
given by the filtration one_filtration (num_generators,).
|
|
1938
|
+
"""
|
|
1939
|
+
if one_filtration is not None:
|
|
1940
|
+
self.truc.set_one_filtration(one_filtration)
|
|
1941
|
+
self.truc.compute_persistence()
|
|
1942
|
+
# return self.truc.get_barcode()
|
|
1943
|
+
def get_barcode(self):
|
|
1944
|
+
"""
|
|
1945
|
+
Returns the barcode of the current 1d-persistence.
|
|
1946
|
+
"""
|
|
1947
|
+
return self.truc.get_barcode()
|
|
1948
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
1949
|
+
"""
|
|
1950
|
+
Computes the filtration on a line L defined by
|
|
1951
|
+
- a basepoint (num_parameters,) array
|
|
1952
|
+
- an optional direction (num_parameters,) array
|
|
1953
|
+
"""
|
|
1954
|
+
self.push_to_line(basepoint,direction)
|
|
1955
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
1956
|
+
def __len__(self):
|
|
1957
|
+
return self.truc.num_generators()
|
|
1958
|
+
@property
|
|
1959
|
+
def num_generators(self):
|
|
1960
|
+
return self.truc.num_generators()
|
|
1961
|
+
@property
|
|
1962
|
+
def num_parameters(self):
|
|
1963
|
+
return self.truc.num_parameters()
|
|
1964
|
+
def info(self):
|
|
1965
|
+
return self.truc.to_str().decode()
|
|
1966
|
+
def compute_box(self):
|
|
1967
|
+
"""
|
|
1968
|
+
Computes the bounding box of the current persistence.
|
|
1969
|
+
"""
|
|
1970
|
+
cdef pair[Finitely_critical_multi_filtration[double],Finitely_critical_multi_filtration[double]] box = self.truc.get_bounding_box()
|
|
1971
|
+
cdef cnp.ndarray[double, ndim=1] a = _ff21cview_f64(&box.first)
|
|
1972
|
+
cdef cnp.ndarray[double, ndim=1] b = _ff21cview_f64(&box.second)
|
|
1973
|
+
return np.asarray([a,b])
|
|
1974
|
+
def get_filtrations_values(self):
|
|
1975
|
+
"""
|
|
1976
|
+
Returns the current filtration values of the slicer.
|
|
1977
|
+
"""
|
|
1978
|
+
cdef vector[Finitely_critical_multi_filtration[double]] v = self.truc.get_filtration_values()
|
|
1979
|
+
out = _vff21cview_f64(v, copy=True)
|
|
1980
|
+
return np.asarray(out)
|
|
1981
|
+
def get_filtrations(self):
|
|
1982
|
+
return _vff21cview_f64(self.truc.get_filtrations(), copy=True)
|
|
1983
|
+
|
|
1984
|
+
def get_dimensions(self):
|
|
1985
|
+
"""
|
|
1986
|
+
Returns the ordered dimensions of the generators.
|
|
1987
|
+
"""
|
|
1988
|
+
return np.asarray(self.truc.get_dimensions())
|
|
1989
|
+
def get_boundaries(self):
|
|
1990
|
+
"""
|
|
1991
|
+
Returns the boundaries of the generators.
|
|
1992
|
+
"""
|
|
1993
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
1994
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
1995
|
+
"""
|
|
1996
|
+
Squeeze the filtration values on a grid.
|
|
1997
|
+
"""
|
|
1998
|
+
if force and self.is_squeezed:
|
|
1999
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2000
|
+
if filtration_grid is None:
|
|
2001
|
+
filtration_grid = mpg.compute_grid(
|
|
2002
|
+
self.get_filtrations_values().T,
|
|
2003
|
+
strategy=grid_strategy,
|
|
2004
|
+
resolution=resolution)
|
|
2005
|
+
cdef vector[vector[double]] grid = filtration_grid
|
|
2006
|
+
if inplace or not coordinates:
|
|
2007
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2008
|
+
self.filtration_grid = filtration_grid
|
|
2009
|
+
else:
|
|
2010
|
+
out = _Slicer0_vine_i32()
|
|
2011
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2012
|
+
out.filtration_grid = filtration_grid
|
|
2013
|
+
return out
|
|
2014
|
+
return self
|
|
2015
|
+
def minpres(self,
|
|
2016
|
+
int degree = 1,
|
|
2017
|
+
list[int] degrees=[],
|
|
2018
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2019
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
2020
|
+
bool vineyard=True,
|
|
2021
|
+
id :Optional[str] = None,
|
|
2022
|
+
dtype = np.float64,
|
|
2023
|
+
**minpres_kwargs
|
|
2024
|
+
):
|
|
2025
|
+
"""
|
|
2026
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
2027
|
+
"""
|
|
2028
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
2029
|
+
return new_slicer
|
|
2030
|
+
|
|
2031
|
+
@property
|
|
2032
|
+
def dtype(self)->type:
|
|
2033
|
+
return np.float64
|
|
2034
|
+
@property
|
|
2035
|
+
def col_type(self)->str:
|
|
2036
|
+
return "INTRUSIVE_SET"
|
|
2037
|
+
@property
|
|
2038
|
+
def is_vine(self)->bool:
|
|
2039
|
+
return True
|
|
2040
|
+
@property
|
|
2041
|
+
def is_kcritical(self)->bool:
|
|
2042
|
+
return False
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
def vine_update(self,basepoint,direction=None):
|
|
2046
|
+
"""
|
|
2047
|
+
Updates the barcode, on a line, using the vineyard algorithm.
|
|
2048
|
+
"""
|
|
2049
|
+
self.push_to_line(basepoint,direction)
|
|
2050
|
+
self.truc.vineyard_update()
|
|
2051
|
+
return self
|
|
2052
|
+
def get_representative_cycles(self, bool update=True):
|
|
2053
|
+
"""
|
|
2054
|
+
Returns the representative cycles of the current barcode.
|
|
2055
|
+
Recomputes the generators if update=True
|
|
2056
|
+
"""
|
|
2057
|
+
return self.truc.get_representative_cycles(update)
|
|
2058
|
+
def get_permutation(self):
|
|
2059
|
+
"""
|
|
2060
|
+
Returns the current generator permutation (w.r.t. vineyard).
|
|
2061
|
+
"""
|
|
2062
|
+
return self.truc.get_current_order()
|
|
2063
|
+
|
|
2064
|
+
@staticmethod
|
|
2065
|
+
def from_bitmap(self):
|
|
2066
|
+
raise ValueError("Not implemented.")
|
|
2067
|
+
|
|
2068
|
+
#------------------------------------------------------------------------------
|
|
2069
|
+
cdef class _KSlicer0_i32:
|
|
2070
|
+
cdef C_KSlicer0_i32 truc
|
|
2071
|
+
cdef public vector[vector[double]] filtration_grid
|
|
2072
|
+
@property
|
|
2073
|
+
def is_squeezed(self)->bool:
|
|
2074
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
2075
|
+
|
|
2076
|
+
def get_ptr(self):
|
|
2077
|
+
"""
|
|
2078
|
+
Returns a pointer to the underlying C++ slicer.
|
|
2079
|
+
"""
|
|
2080
|
+
return <intptr_t>(&self.truc)
|
|
2081
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2082
|
+
"""
|
|
2083
|
+
Constructs a slicer from
|
|
2084
|
+
- scc-like blocks
|
|
2085
|
+
or
|
|
2086
|
+
- generator maps (Iterable of list of ints)
|
|
2087
|
+
- generator dimensions (Iterable of int)
|
|
2088
|
+
- filtration values (Iterable of filtration values)
|
|
2089
|
+
"""
|
|
2090
|
+
pass
|
|
2091
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2092
|
+
"""
|
|
2093
|
+
Cython constructor
|
|
2094
|
+
"""
|
|
2095
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
2096
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
2097
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
2098
|
+
generator_maps,
|
|
2099
|
+
inplace=False,
|
|
2100
|
+
)
|
|
2101
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
2102
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
2103
|
+
cdef vector[KCriticalFiltration[int32_t]] c_filtration_values
|
|
2104
|
+
for stuff in generator_maps:
|
|
2105
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
2106
|
+
cdef KCriticalFiltration[int32_t] cf
|
|
2107
|
+
for F in filtration_values:
|
|
2108
|
+
cf.clear()
|
|
2109
|
+
for f in F:
|
|
2110
|
+
cf.add_point(_py21c_i32(f))
|
|
2111
|
+
c_filtration_values.push_back(cf)
|
|
2112
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
2113
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
2114
|
+
self.truc = C_KSlicer0_i32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
2115
|
+
def copy(self):
|
|
2116
|
+
"""
|
|
2117
|
+
Returns a copy of the slicer.
|
|
2118
|
+
"""
|
|
2119
|
+
copy_ = _KSlicer0_i32()
|
|
2120
|
+
copy_.truc = self.truc
|
|
2121
|
+
return copy_
|
|
2122
|
+
def get_barcode(self):
|
|
2123
|
+
"""
|
|
2124
|
+
Returns the current barcode.
|
|
2125
|
+
"""
|
|
2126
|
+
return self.truc.get_barcode()
|
|
2127
|
+
def push_to_line(self, basepoint, direction=None):
|
|
2128
|
+
"""
|
|
2129
|
+
Pushes the current slicer to the line
|
|
2130
|
+
"""
|
|
2131
|
+
cdef Line[int32_t] line
|
|
2132
|
+
if direction is None:
|
|
2133
|
+
line = Line[int32_t](_py21c_i32(basepoint))
|
|
2134
|
+
else:
|
|
2135
|
+
line = Line[int32_t](_py21c_i32(basepoint),_py21c_i32(direction))
|
|
2136
|
+
self.truc.push_to(line)
|
|
2137
|
+
return self
|
|
2138
|
+
|
|
2139
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
2140
|
+
"""
|
|
2141
|
+
Computes the persistence on a line L defined by
|
|
2142
|
+
- a basepoint (num_parameters,) array
|
|
2143
|
+
- an optional direction (num_parameters,) array
|
|
2144
|
+
"""
|
|
2145
|
+
self.push_to_line(basepoint,direction)
|
|
2146
|
+
self.truc.compute_persistence()
|
|
2147
|
+
return self.truc.get_barcode()
|
|
2148
|
+
def compute_persistence(self,one_filtration=None):
|
|
2149
|
+
"""
|
|
2150
|
+
Computes the current persistence, or the persistence
|
|
2151
|
+
given by the filtration one_filtration (num_generators,).
|
|
2152
|
+
"""
|
|
2153
|
+
if one_filtration is not None:
|
|
2154
|
+
self.truc.set_one_filtration(one_filtration)
|
|
2155
|
+
self.truc.compute_persistence()
|
|
2156
|
+
# return self.truc.get_barcode()
|
|
2157
|
+
def get_barcode(self):
|
|
2158
|
+
"""
|
|
2159
|
+
Returns the barcode of the current 1d-persistence.
|
|
2160
|
+
"""
|
|
2161
|
+
return self.truc.get_barcode()
|
|
2162
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
2163
|
+
"""
|
|
2164
|
+
Computes the filtration on a line L defined by
|
|
2165
|
+
- a basepoint (num_parameters,) array
|
|
2166
|
+
- an optional direction (num_parameters,) array
|
|
2167
|
+
"""
|
|
2168
|
+
self.push_to_line(basepoint,direction)
|
|
2169
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
2170
|
+
def __len__(self):
|
|
2171
|
+
return self.truc.num_generators()
|
|
2172
|
+
@property
|
|
2173
|
+
def num_generators(self):
|
|
2174
|
+
return self.truc.num_generators()
|
|
2175
|
+
@property
|
|
2176
|
+
def num_parameters(self):
|
|
2177
|
+
return self.truc.num_parameters()
|
|
2178
|
+
def info(self):
|
|
2179
|
+
return self.truc.to_str().decode()
|
|
2180
|
+
def compute_box(self):
|
|
2181
|
+
"""
|
|
2182
|
+
Computes the bounding box of the current persistence.
|
|
2183
|
+
"""
|
|
2184
|
+
cdef pair[Finitely_critical_multi_filtration[int32_t],Finitely_critical_multi_filtration[int32_t]] box = self.truc.get_bounding_box()
|
|
2185
|
+
cdef cnp.ndarray[int32_t, ndim=1] a = _ff21cview_i32(&box.first)
|
|
2186
|
+
cdef cnp.ndarray[int32_t, ndim=1] b = _ff21cview_i32(&box.second)
|
|
2187
|
+
return np.asarray([a,b])
|
|
2188
|
+
def get_filtrations_values(self):
|
|
2189
|
+
"""
|
|
2190
|
+
Returns the current filtration values of the slicer.
|
|
2191
|
+
"""
|
|
2192
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] v = self.truc.get_filtration_values()
|
|
2193
|
+
out = _vff21cview_i32(v, copy=True)
|
|
2194
|
+
return np.asarray(out)
|
|
2195
|
+
def get_filtrations(self):
|
|
2196
|
+
return _vff2kcview_i32(self.truc.get_filtrations(), copy=True)
|
|
2197
|
+
|
|
2198
|
+
def get_dimensions(self):
|
|
2199
|
+
"""
|
|
2200
|
+
Returns the ordered dimensions of the generators.
|
|
2201
|
+
"""
|
|
2202
|
+
return np.asarray(self.truc.get_dimensions())
|
|
2203
|
+
def get_boundaries(self):
|
|
2204
|
+
"""
|
|
2205
|
+
Returns the boundaries of the generators.
|
|
2206
|
+
"""
|
|
2207
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
2208
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
2209
|
+
"""
|
|
2210
|
+
Squeeze the filtration values on a grid.
|
|
2211
|
+
"""
|
|
2212
|
+
if force and self.is_squeezed:
|
|
2213
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2214
|
+
if filtration_grid is None:
|
|
2215
|
+
filtration_grid = mpg.compute_grid(
|
|
2216
|
+
self.get_filtrations_values().T,
|
|
2217
|
+
strategy=grid_strategy,
|
|
2218
|
+
resolution=resolution)
|
|
2219
|
+
cdef vector[vector[int32_t]] grid = filtration_grid
|
|
2220
|
+
if inplace or not coordinates:
|
|
2221
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2222
|
+
self.filtration_grid = filtration_grid
|
|
2223
|
+
else:
|
|
2224
|
+
out = _KSlicer0_i32()
|
|
2225
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2226
|
+
out.filtration_grid = filtration_grid
|
|
2227
|
+
return out
|
|
2228
|
+
return self
|
|
2229
|
+
def minpres(self,
|
|
2230
|
+
int degree = 1,
|
|
2231
|
+
list[int] degrees=[],
|
|
2232
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2233
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
2234
|
+
bool vineyard=False,
|
|
2235
|
+
id :Optional[str] = None,
|
|
2236
|
+
dtype = np.int32,
|
|
2237
|
+
**minpres_kwargs
|
|
2238
|
+
):
|
|
2239
|
+
"""
|
|
2240
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
2241
|
+
"""
|
|
2242
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
2243
|
+
return new_slicer
|
|
2244
|
+
|
|
2245
|
+
@property
|
|
2246
|
+
def dtype(self)->type:
|
|
2247
|
+
return np.int32
|
|
2248
|
+
@property
|
|
2249
|
+
def col_type(self)->str:
|
|
2250
|
+
return "INTRUSIVE_SET"
|
|
2251
|
+
@property
|
|
2252
|
+
def is_vine(self)->bool:
|
|
2253
|
+
return False
|
|
2254
|
+
@property
|
|
2255
|
+
def is_kcritical(self)->bool:
|
|
2256
|
+
return True
|
|
2257
|
+
|
|
2258
|
+
|
|
2259
|
+
|
|
2260
|
+
@staticmethod
|
|
2261
|
+
def from_bitmap(self):
|
|
2262
|
+
raise ValueError("Not implemented.")
|
|
2263
|
+
|
|
2264
|
+
#------------------------------------------------------------------------------
|
|
2265
|
+
cdef class _KSlicer0_f32:
|
|
2266
|
+
cdef C_KSlicer0_f32 truc
|
|
2267
|
+
cdef public vector[vector[double]] filtration_grid
|
|
2268
|
+
@property
|
|
2269
|
+
def is_squeezed(self)->bool:
|
|
2270
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
2271
|
+
|
|
2272
|
+
def get_ptr(self):
|
|
2273
|
+
"""
|
|
2274
|
+
Returns a pointer to the underlying C++ slicer.
|
|
2275
|
+
"""
|
|
2276
|
+
return <intptr_t>(&self.truc)
|
|
2277
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2278
|
+
"""
|
|
2279
|
+
Constructs a slicer from
|
|
2280
|
+
- scc-like blocks
|
|
2281
|
+
or
|
|
2282
|
+
- generator maps (Iterable of list of ints)
|
|
2283
|
+
- generator dimensions (Iterable of int)
|
|
2284
|
+
- filtration values (Iterable of filtration values)
|
|
2285
|
+
"""
|
|
2286
|
+
pass
|
|
2287
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2288
|
+
"""
|
|
2289
|
+
Cython constructor
|
|
2290
|
+
"""
|
|
2291
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
2292
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
2293
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
2294
|
+
generator_maps,
|
|
2295
|
+
inplace=False,
|
|
2296
|
+
)
|
|
2297
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
2298
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
2299
|
+
cdef vector[KCriticalFiltration[float]] c_filtration_values
|
|
2300
|
+
for stuff in generator_maps:
|
|
2301
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
2302
|
+
cdef KCriticalFiltration[float] cf
|
|
2303
|
+
for F in filtration_values:
|
|
2304
|
+
cf.clear()
|
|
2305
|
+
for f in F:
|
|
2306
|
+
cf.add_point(_py21c_f32(f))
|
|
2307
|
+
c_filtration_values.push_back(cf)
|
|
2308
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
2309
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
2310
|
+
self.truc = C_KSlicer0_f32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
2311
|
+
def copy(self):
|
|
2312
|
+
"""
|
|
2313
|
+
Returns a copy of the slicer.
|
|
2314
|
+
"""
|
|
2315
|
+
copy_ = _KSlicer0_f32()
|
|
2316
|
+
copy_.truc = self.truc
|
|
2317
|
+
return copy_
|
|
2318
|
+
def get_barcode(self):
|
|
2319
|
+
"""
|
|
2320
|
+
Returns the current barcode.
|
|
2321
|
+
"""
|
|
2322
|
+
return self.truc.get_barcode()
|
|
2323
|
+
def push_to_line(self, basepoint, direction=None):
|
|
2324
|
+
"""
|
|
2325
|
+
Pushes the current slicer to the line
|
|
2326
|
+
"""
|
|
2327
|
+
cdef Line[float] line
|
|
2328
|
+
if direction is None:
|
|
2329
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
2330
|
+
else:
|
|
2331
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
2332
|
+
self.truc.push_to(line)
|
|
2333
|
+
return self
|
|
2334
|
+
|
|
2335
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
2336
|
+
"""
|
|
2337
|
+
Computes the persistence on a line L defined by
|
|
2338
|
+
- a basepoint (num_parameters,) array
|
|
2339
|
+
- an optional direction (num_parameters,) array
|
|
2340
|
+
"""
|
|
2341
|
+
self.push_to_line(basepoint,direction)
|
|
2342
|
+
self.truc.compute_persistence()
|
|
2343
|
+
return self.truc.get_barcode()
|
|
2344
|
+
def compute_persistence(self,one_filtration=None):
|
|
2345
|
+
"""
|
|
2346
|
+
Computes the current persistence, or the persistence
|
|
2347
|
+
given by the filtration one_filtration (num_generators,).
|
|
2348
|
+
"""
|
|
2349
|
+
if one_filtration is not None:
|
|
2350
|
+
self.truc.set_one_filtration(one_filtration)
|
|
2351
|
+
self.truc.compute_persistence()
|
|
2352
|
+
# return self.truc.get_barcode()
|
|
2353
|
+
def get_barcode(self):
|
|
2354
|
+
"""
|
|
2355
|
+
Returns the barcode of the current 1d-persistence.
|
|
2356
|
+
"""
|
|
2357
|
+
return self.truc.get_barcode()
|
|
2358
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
2359
|
+
"""
|
|
2360
|
+
Computes the filtration on a line L defined by
|
|
2361
|
+
- a basepoint (num_parameters,) array
|
|
2362
|
+
- an optional direction (num_parameters,) array
|
|
2363
|
+
"""
|
|
2364
|
+
self.push_to_line(basepoint,direction)
|
|
2365
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
2366
|
+
def __len__(self):
|
|
2367
|
+
return self.truc.num_generators()
|
|
2368
|
+
@property
|
|
2369
|
+
def num_generators(self):
|
|
2370
|
+
return self.truc.num_generators()
|
|
2371
|
+
@property
|
|
2372
|
+
def num_parameters(self):
|
|
2373
|
+
return self.truc.num_parameters()
|
|
2374
|
+
def info(self):
|
|
2375
|
+
return self.truc.to_str().decode()
|
|
2376
|
+
def compute_box(self):
|
|
2377
|
+
"""
|
|
2378
|
+
Computes the bounding box of the current persistence.
|
|
2379
|
+
"""
|
|
2380
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
2381
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
2382
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
2383
|
+
return np.asarray([a,b])
|
|
2384
|
+
def get_filtrations_values(self):
|
|
2385
|
+
"""
|
|
2386
|
+
Returns the current filtration values of the slicer.
|
|
2387
|
+
"""
|
|
2388
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
2389
|
+
out = _vff21cview_f32(v, copy=True)
|
|
2390
|
+
return np.asarray(out)
|
|
2391
|
+
def get_filtrations(self):
|
|
2392
|
+
return _vff2kcview_f32(self.truc.get_filtrations(), copy=True)
|
|
2393
|
+
|
|
2394
|
+
def get_dimensions(self):
|
|
2395
|
+
"""
|
|
2396
|
+
Returns the ordered dimensions of the generators.
|
|
2397
|
+
"""
|
|
2398
|
+
return np.asarray(self.truc.get_dimensions())
|
|
2399
|
+
def get_boundaries(self):
|
|
2400
|
+
"""
|
|
2401
|
+
Returns the boundaries of the generators.
|
|
2402
|
+
"""
|
|
2403
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
2404
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
2405
|
+
"""
|
|
2406
|
+
Squeeze the filtration values on a grid.
|
|
2407
|
+
"""
|
|
2408
|
+
if force and self.is_squeezed:
|
|
2409
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2410
|
+
if filtration_grid is None:
|
|
2411
|
+
filtration_grid = mpg.compute_grid(
|
|
2412
|
+
self.get_filtrations_values().T,
|
|
2413
|
+
strategy=grid_strategy,
|
|
2414
|
+
resolution=resolution)
|
|
2415
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
2416
|
+
if inplace or not coordinates:
|
|
2417
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2418
|
+
self.filtration_grid = filtration_grid
|
|
2419
|
+
else:
|
|
2420
|
+
out = _KSlicer0_i32()
|
|
2421
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2422
|
+
out.filtration_grid = filtration_grid
|
|
2423
|
+
return out
|
|
2424
|
+
return self
|
|
2425
|
+
def minpres(self,
|
|
2426
|
+
int degree = 1,
|
|
2427
|
+
list[int] degrees=[],
|
|
2428
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2429
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
2430
|
+
bool vineyard=False,
|
|
2431
|
+
id :Optional[str] = None,
|
|
2432
|
+
dtype = np.float32,
|
|
2433
|
+
**minpres_kwargs
|
|
2434
|
+
):
|
|
2435
|
+
"""
|
|
2436
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
2437
|
+
"""
|
|
2438
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
2439
|
+
return new_slicer
|
|
2440
|
+
|
|
2441
|
+
@property
|
|
2442
|
+
def dtype(self)->type:
|
|
2443
|
+
return np.float32
|
|
2444
|
+
@property
|
|
2445
|
+
def col_type(self)->str:
|
|
2446
|
+
return "INTRUSIVE_SET"
|
|
2447
|
+
@property
|
|
2448
|
+
def is_vine(self)->bool:
|
|
2449
|
+
return False
|
|
2450
|
+
@property
|
|
2451
|
+
def is_kcritical(self)->bool:
|
|
2452
|
+
return True
|
|
2453
|
+
|
|
2454
|
+
|
|
2455
|
+
|
|
2456
|
+
@staticmethod
|
|
2457
|
+
def from_bitmap(self):
|
|
2458
|
+
raise ValueError("Not implemented.")
|
|
2459
|
+
|
|
2460
|
+
#------------------------------------------------------------------------------
|
|
2461
|
+
cdef class _KSlicer0_f64:
|
|
2462
|
+
cdef C_KSlicer0_f64 truc
|
|
2463
|
+
cdef public vector[vector[double]] filtration_grid
|
|
2464
|
+
@property
|
|
2465
|
+
def is_squeezed(self)->bool:
|
|
2466
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
2467
|
+
|
|
2468
|
+
def get_ptr(self):
|
|
2469
|
+
"""
|
|
2470
|
+
Returns a pointer to the underlying C++ slicer.
|
|
2471
|
+
"""
|
|
2472
|
+
return <intptr_t>(&self.truc)
|
|
2473
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2474
|
+
"""
|
|
2475
|
+
Constructs a slicer from
|
|
2476
|
+
- scc-like blocks
|
|
2477
|
+
or
|
|
2478
|
+
- generator maps (Iterable of list of ints)
|
|
2479
|
+
- generator dimensions (Iterable of int)
|
|
2480
|
+
- filtration values (Iterable of filtration values)
|
|
2481
|
+
"""
|
|
2482
|
+
pass
|
|
2483
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2484
|
+
"""
|
|
2485
|
+
Cython constructor
|
|
2486
|
+
"""
|
|
2487
|
+
if len(generator_maps)>0 and len(generator_dimensions) == 0 and len(filtration_values) == 0:
|
|
2488
|
+
from multipers._slicer_meta import _blocks2boundary_dimension_grades
|
|
2489
|
+
generator_maps, generator_dimensions, filtration_values = _blocks2boundary_dimension_grades(
|
|
2490
|
+
generator_maps,
|
|
2491
|
+
inplace=False,
|
|
2492
|
+
)
|
|
2493
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
2494
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
2495
|
+
cdef vector[KCriticalFiltration[double]] c_filtration_values
|
|
2496
|
+
for stuff in generator_maps:
|
|
2497
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
2498
|
+
cdef KCriticalFiltration[double] cf
|
|
2499
|
+
for F in filtration_values:
|
|
2500
|
+
cf.clear()
|
|
2501
|
+
for f in F:
|
|
2502
|
+
cf.add_point(_py21c_f64(f))
|
|
2503
|
+
c_filtration_values.push_back(cf)
|
|
2504
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
2505
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
2506
|
+
self.truc = C_KSlicer0_f64(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
2507
|
+
def copy(self):
|
|
2508
|
+
"""
|
|
2509
|
+
Returns a copy of the slicer.
|
|
2510
|
+
"""
|
|
2511
|
+
copy_ = _KSlicer0_f64()
|
|
2512
|
+
copy_.truc = self.truc
|
|
2513
|
+
return copy_
|
|
2514
|
+
def get_barcode(self):
|
|
2515
|
+
"""
|
|
2516
|
+
Returns the current barcode.
|
|
2517
|
+
"""
|
|
2518
|
+
return self.truc.get_barcode()
|
|
2519
|
+
def push_to_line(self, basepoint, direction=None):
|
|
2520
|
+
"""
|
|
2521
|
+
Pushes the current slicer to the line
|
|
2522
|
+
"""
|
|
2523
|
+
cdef Line[double] line
|
|
2524
|
+
if direction is None:
|
|
2525
|
+
line = Line[double](_py21c_f64(basepoint))
|
|
2526
|
+
else:
|
|
2527
|
+
line = Line[double](_py21c_f64(basepoint),_py21c_f64(direction))
|
|
2528
|
+
self.truc.push_to(line)
|
|
2529
|
+
return self
|
|
2530
|
+
|
|
2531
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
2532
|
+
"""
|
|
2533
|
+
Computes the persistence on a line L defined by
|
|
2534
|
+
- a basepoint (num_parameters,) array
|
|
2535
|
+
- an optional direction (num_parameters,) array
|
|
2536
|
+
"""
|
|
2537
|
+
self.push_to_line(basepoint,direction)
|
|
2538
|
+
self.truc.compute_persistence()
|
|
2539
|
+
return self.truc.get_barcode()
|
|
2540
|
+
def compute_persistence(self,one_filtration=None):
|
|
2541
|
+
"""
|
|
2542
|
+
Computes the current persistence, or the persistence
|
|
2543
|
+
given by the filtration one_filtration (num_generators,).
|
|
2544
|
+
"""
|
|
2545
|
+
if one_filtration is not None:
|
|
2546
|
+
self.truc.set_one_filtration(one_filtration)
|
|
2547
|
+
self.truc.compute_persistence()
|
|
2548
|
+
# return self.truc.get_barcode()
|
|
2549
|
+
def get_barcode(self):
|
|
2550
|
+
"""
|
|
2551
|
+
Returns the barcode of the current 1d-persistence.
|
|
2552
|
+
"""
|
|
2553
|
+
return self.truc.get_barcode()
|
|
2554
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
2555
|
+
"""
|
|
2556
|
+
Computes the filtration on a line L defined by
|
|
2557
|
+
- a basepoint (num_parameters,) array
|
|
2558
|
+
- an optional direction (num_parameters,) array
|
|
2559
|
+
"""
|
|
2560
|
+
self.push_to_line(basepoint,direction)
|
|
2561
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
2562
|
+
def __len__(self):
|
|
2563
|
+
return self.truc.num_generators()
|
|
2564
|
+
@property
|
|
2565
|
+
def num_generators(self):
|
|
2566
|
+
return self.truc.num_generators()
|
|
2567
|
+
@property
|
|
2568
|
+
def num_parameters(self):
|
|
2569
|
+
return self.truc.num_parameters()
|
|
2570
|
+
def info(self):
|
|
2571
|
+
return self.truc.to_str().decode()
|
|
2572
|
+
def compute_box(self):
|
|
2573
|
+
"""
|
|
2574
|
+
Computes the bounding box of the current persistence.
|
|
2575
|
+
"""
|
|
2576
|
+
cdef pair[Finitely_critical_multi_filtration[double],Finitely_critical_multi_filtration[double]] box = self.truc.get_bounding_box()
|
|
2577
|
+
cdef cnp.ndarray[double, ndim=1] a = _ff21cview_f64(&box.first)
|
|
2578
|
+
cdef cnp.ndarray[double, ndim=1] b = _ff21cview_f64(&box.second)
|
|
2579
|
+
return np.asarray([a,b])
|
|
2580
|
+
def get_filtrations_values(self):
|
|
2581
|
+
"""
|
|
2582
|
+
Returns the current filtration values of the slicer.
|
|
2583
|
+
"""
|
|
2584
|
+
cdef vector[Finitely_critical_multi_filtration[double]] v = self.truc.get_filtration_values()
|
|
2585
|
+
out = _vff21cview_f64(v, copy=True)
|
|
2586
|
+
return np.asarray(out)
|
|
2587
|
+
def get_filtrations(self):
|
|
2588
|
+
return _vff2kcview_f64(self.truc.get_filtrations(), copy=True)
|
|
2589
|
+
|
|
2590
|
+
def get_dimensions(self):
|
|
2591
|
+
"""
|
|
2592
|
+
Returns the ordered dimensions of the generators.
|
|
2593
|
+
"""
|
|
2594
|
+
return np.asarray(self.truc.get_dimensions())
|
|
2595
|
+
def get_boundaries(self):
|
|
2596
|
+
"""
|
|
2597
|
+
Returns the boundaries of the generators.
|
|
2598
|
+
"""
|
|
2599
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
2600
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
2601
|
+
"""
|
|
2602
|
+
Squeeze the filtration values on a grid.
|
|
2603
|
+
"""
|
|
2604
|
+
if force and self.is_squeezed:
|
|
2605
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2606
|
+
if filtration_grid is None:
|
|
2607
|
+
filtration_grid = mpg.compute_grid(
|
|
2608
|
+
self.get_filtrations_values().T,
|
|
2609
|
+
strategy=grid_strategy,
|
|
2610
|
+
resolution=resolution)
|
|
2611
|
+
cdef vector[vector[double]] grid = filtration_grid
|
|
2612
|
+
if inplace or not coordinates:
|
|
2613
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2614
|
+
self.filtration_grid = filtration_grid
|
|
2615
|
+
else:
|
|
2616
|
+
out = _KSlicer0_i32()
|
|
2617
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2618
|
+
out.filtration_grid = filtration_grid
|
|
2619
|
+
return out
|
|
2620
|
+
return self
|
|
2621
|
+
def minpres(self,
|
|
2622
|
+
int degree = 1,
|
|
2623
|
+
list[int] degrees=[],
|
|
2624
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2625
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
2626
|
+
bool vineyard=False,
|
|
2627
|
+
id :Optional[str] = None,
|
|
2628
|
+
dtype = np.float64,
|
|
2629
|
+
**minpres_kwargs
|
|
2630
|
+
):
|
|
2631
|
+
"""
|
|
2632
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
2633
|
+
"""
|
|
2634
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
2635
|
+
return new_slicer
|
|
2636
|
+
|
|
2637
|
+
@property
|
|
2638
|
+
def dtype(self)->type:
|
|
2639
|
+
return np.float64
|
|
2640
|
+
@property
|
|
2641
|
+
def col_type(self)->str:
|
|
2642
|
+
return "INTRUSIVE_SET"
|
|
2643
|
+
@property
|
|
2644
|
+
def is_vine(self)->bool:
|
|
2645
|
+
return False
|
|
2646
|
+
@property
|
|
2647
|
+
def is_kcritical(self)->bool:
|
|
2648
|
+
return True
|
|
2649
|
+
|
|
2650
|
+
|
|
2651
|
+
|
|
2652
|
+
@staticmethod
|
|
2653
|
+
def from_bitmap(self):
|
|
2654
|
+
raise ValueError("Not implemented.")
|
|
2655
|
+
|
|
2656
|
+
#------------------------------------------------------------------------------
|
|
2657
|
+
cdef class _Slicer0_i32:
|
|
2658
|
+
cdef C_Slicer0_i32 truc
|
|
2659
|
+
cdef public vector[vector[double]] filtration_grid
|
|
2660
|
+
@property
|
|
2661
|
+
def is_squeezed(self)->bool:
|
|
2662
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
2663
|
+
|
|
2664
|
+
def get_ptr(self):
|
|
2665
|
+
"""
|
|
2666
|
+
Returns a pointer to the underlying C++ slicer.
|
|
2667
|
+
"""
|
|
2668
|
+
return <intptr_t>(&self.truc)
|
|
2669
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2670
|
+
"""
|
|
2671
|
+
Constructs a slicer from
|
|
2672
|
+
- generator maps (Iterable of list of ints)
|
|
2673
|
+
- generator dimensions (Iterable of int)
|
|
2674
|
+
- filtration values (Iterable of filtration values)
|
|
2675
|
+
"""
|
|
2676
|
+
pass
|
|
2677
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2678
|
+
"""
|
|
2679
|
+
Cython constructor
|
|
2680
|
+
"""
|
|
2681
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
2682
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
2683
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] c_filtration_values
|
|
2684
|
+
for stuff in generator_maps:
|
|
2685
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
2686
|
+
for f in filtration_values:
|
|
2687
|
+
# cf.clear()
|
|
2688
|
+
# for truc in f:
|
|
2689
|
+
# cf.push_back(truc)
|
|
2690
|
+
c_filtration_values.push_back(_py21c_i32(f))
|
|
2691
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
2692
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
2693
|
+
self.truc = C_Slicer0_i32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
2694
|
+
def copy(self):
|
|
2695
|
+
"""
|
|
2696
|
+
Returns a copy of the slicer.
|
|
2697
|
+
"""
|
|
2698
|
+
copy_ = _Slicer0_i32()
|
|
2699
|
+
copy_.truc = self.truc
|
|
2700
|
+
return copy_
|
|
2701
|
+
def get_barcode(self):
|
|
2702
|
+
"""
|
|
2703
|
+
Returns the current barcode.
|
|
2704
|
+
"""
|
|
2705
|
+
return self.truc.get_barcode()
|
|
2706
|
+
def push_to_line(self, basepoint, direction=None):
|
|
2707
|
+
"""
|
|
2708
|
+
Pushes the current slicer to the line
|
|
2709
|
+
"""
|
|
2710
|
+
cdef Line[int32_t] line
|
|
2711
|
+
if direction is None:
|
|
2712
|
+
line = Line[int32_t](_py21c_i32(basepoint))
|
|
2713
|
+
else:
|
|
2714
|
+
line = Line[int32_t](_py21c_i32(basepoint),_py21c_i32(direction))
|
|
2715
|
+
self.truc.push_to(line)
|
|
2716
|
+
return self
|
|
2717
|
+
|
|
2718
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
2719
|
+
"""
|
|
2720
|
+
Computes the persistence on a line L defined by
|
|
2721
|
+
- a basepoint (num_parameters,) array
|
|
2722
|
+
- an optional direction (num_parameters,) array
|
|
2723
|
+
"""
|
|
2724
|
+
self.push_to_line(basepoint,direction)
|
|
2725
|
+
self.truc.compute_persistence()
|
|
2726
|
+
return self.truc.get_barcode()
|
|
2727
|
+
def compute_persistence(self,one_filtration=None):
|
|
2728
|
+
"""
|
|
2729
|
+
Computes the current persistence, or the persistence
|
|
2730
|
+
given by the filtration one_filtration (num_generators,).
|
|
2731
|
+
"""
|
|
2732
|
+
if one_filtration is not None:
|
|
2733
|
+
self.truc.set_one_filtration(one_filtration)
|
|
2734
|
+
self.truc.compute_persistence()
|
|
2735
|
+
# return self.truc.get_barcode()
|
|
2736
|
+
def get_barcode(self):
|
|
2737
|
+
"""
|
|
2738
|
+
Returns the barcode of the current 1d-persistence.
|
|
2739
|
+
"""
|
|
2740
|
+
return self.truc.get_barcode()
|
|
2741
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
2742
|
+
"""
|
|
2743
|
+
Computes the filtration on a line L defined by
|
|
2744
|
+
- a basepoint (num_parameters,) array
|
|
2745
|
+
- an optional direction (num_parameters,) array
|
|
2746
|
+
"""
|
|
2747
|
+
self.push_to_line(basepoint,direction)
|
|
2748
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
2749
|
+
def __len__(self):
|
|
2750
|
+
return self.truc.num_generators()
|
|
2751
|
+
@property
|
|
2752
|
+
def num_generators(self):
|
|
2753
|
+
return self.truc.num_generators()
|
|
2754
|
+
@property
|
|
2755
|
+
def num_parameters(self):
|
|
2756
|
+
return self.truc.num_parameters()
|
|
2757
|
+
def info(self):
|
|
2758
|
+
return self.truc.to_str().decode()
|
|
2759
|
+
def compute_box(self):
|
|
2760
|
+
"""
|
|
2761
|
+
Computes the bounding box of the current persistence.
|
|
2762
|
+
"""
|
|
2763
|
+
cdef pair[Finitely_critical_multi_filtration[int32_t],Finitely_critical_multi_filtration[int32_t]] box = self.truc.get_bounding_box()
|
|
2764
|
+
cdef cnp.ndarray[int32_t, ndim=1] a = _ff21cview_i32(&box.first)
|
|
2765
|
+
cdef cnp.ndarray[int32_t, ndim=1] b = _ff21cview_i32(&box.second)
|
|
2766
|
+
return np.asarray([a,b])
|
|
2767
|
+
def get_filtrations_values(self):
|
|
2768
|
+
"""
|
|
2769
|
+
Returns the current filtration values of the slicer.
|
|
2770
|
+
"""
|
|
2771
|
+
cdef vector[Finitely_critical_multi_filtration[int32_t]] v = self.truc.get_filtration_values()
|
|
2772
|
+
out = _vff21cview_i32(v, copy=True)
|
|
2773
|
+
return np.asarray(out)
|
|
2774
|
+
def get_filtrations(self):
|
|
2775
|
+
return _vff21cview_i32(self.truc.get_filtrations(), copy=True)
|
|
2776
|
+
|
|
2777
|
+
def get_dimensions(self):
|
|
2778
|
+
"""
|
|
2779
|
+
Returns the ordered dimensions of the generators.
|
|
2780
|
+
"""
|
|
2781
|
+
return np.asarray(self.truc.get_dimensions())
|
|
2782
|
+
def get_boundaries(self):
|
|
2783
|
+
"""
|
|
2784
|
+
Returns the boundaries of the generators.
|
|
2785
|
+
"""
|
|
2786
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
2787
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
2788
|
+
"""
|
|
2789
|
+
Squeeze the filtration values on a grid.
|
|
2790
|
+
"""
|
|
2791
|
+
if force and self.is_squeezed:
|
|
2792
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2793
|
+
if filtration_grid is None:
|
|
2794
|
+
filtration_grid = mpg.compute_grid(
|
|
2795
|
+
self.get_filtrations_values().T,
|
|
2796
|
+
strategy=grid_strategy,
|
|
2797
|
+
resolution=resolution)
|
|
2798
|
+
cdef vector[vector[int32_t]] grid = filtration_grid
|
|
2799
|
+
if inplace or not coordinates:
|
|
2800
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2801
|
+
self.filtration_grid = filtration_grid
|
|
2802
|
+
else:
|
|
2803
|
+
out = _Slicer0_i32()
|
|
2804
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2805
|
+
out.filtration_grid = filtration_grid
|
|
2806
|
+
return out
|
|
2807
|
+
return self
|
|
2808
|
+
def minpres(self,
|
|
2809
|
+
int degree = 1,
|
|
2810
|
+
list[int] degrees=[],
|
|
2811
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2812
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
2813
|
+
bool vineyard=False,
|
|
2814
|
+
id :Optional[str] = None,
|
|
2815
|
+
dtype = np.int32,
|
|
2816
|
+
**minpres_kwargs
|
|
2817
|
+
):
|
|
2818
|
+
"""
|
|
2819
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
2820
|
+
"""
|
|
2821
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
2822
|
+
return new_slicer
|
|
2823
|
+
|
|
2824
|
+
@property
|
|
2825
|
+
def dtype(self)->type:
|
|
2826
|
+
return np.int32
|
|
2827
|
+
@property
|
|
2828
|
+
def col_type(self)->str:
|
|
2829
|
+
return "INTRUSIVE_SET"
|
|
2830
|
+
@property
|
|
2831
|
+
def is_vine(self)->bool:
|
|
2832
|
+
return False
|
|
2833
|
+
@property
|
|
2834
|
+
def is_kcritical(self)->bool:
|
|
2835
|
+
return False
|
|
2836
|
+
|
|
2837
|
+
|
|
2838
|
+
|
|
2839
|
+
@staticmethod
|
|
2840
|
+
def from_bitmap(self):
|
|
2841
|
+
raise ValueError("Not implemented.")
|
|
2842
|
+
|
|
2843
|
+
#------------------------------------------------------------------------------
|
|
2844
|
+
cdef class _Slicer0_f32:
|
|
2845
|
+
cdef C_Slicer0_f32 truc
|
|
2846
|
+
cdef public vector[vector[double]] filtration_grid
|
|
2847
|
+
@property
|
|
2848
|
+
def is_squeezed(self)->bool:
|
|
2849
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
2850
|
+
|
|
2851
|
+
def get_ptr(self):
|
|
2852
|
+
"""
|
|
2853
|
+
Returns a pointer to the underlying C++ slicer.
|
|
2854
|
+
"""
|
|
2855
|
+
return <intptr_t>(&self.truc)
|
|
2856
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2857
|
+
"""
|
|
2858
|
+
Constructs a slicer from
|
|
2859
|
+
- generator maps (Iterable of list of ints)
|
|
2860
|
+
- generator dimensions (Iterable of int)
|
|
2861
|
+
- filtration values (Iterable of filtration values)
|
|
2862
|
+
"""
|
|
2863
|
+
pass
|
|
2864
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
2865
|
+
"""
|
|
2866
|
+
Cython constructor
|
|
2867
|
+
"""
|
|
2868
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
2869
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
2870
|
+
cdef vector[Finitely_critical_multi_filtration[float]] c_filtration_values
|
|
2871
|
+
for stuff in generator_maps:
|
|
2872
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
2873
|
+
for f in filtration_values:
|
|
2874
|
+
# cf.clear()
|
|
2875
|
+
# for truc in f:
|
|
2876
|
+
# cf.push_back(truc)
|
|
2877
|
+
c_filtration_values.push_back(_py21c_f32(f))
|
|
2878
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
2879
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
2880
|
+
self.truc = C_Slicer0_f32(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
2881
|
+
def copy(self):
|
|
2882
|
+
"""
|
|
2883
|
+
Returns a copy of the slicer.
|
|
2884
|
+
"""
|
|
2885
|
+
copy_ = _Slicer0_f32()
|
|
2886
|
+
copy_.truc = self.truc
|
|
2887
|
+
return copy_
|
|
2888
|
+
def get_barcode(self):
|
|
2889
|
+
"""
|
|
2890
|
+
Returns the current barcode.
|
|
2891
|
+
"""
|
|
2892
|
+
return self.truc.get_barcode()
|
|
2893
|
+
def push_to_line(self, basepoint, direction=None):
|
|
2894
|
+
"""
|
|
2895
|
+
Pushes the current slicer to the line
|
|
2896
|
+
"""
|
|
2897
|
+
cdef Line[float] line
|
|
2898
|
+
if direction is None:
|
|
2899
|
+
line = Line[float](_py21c_f32(basepoint))
|
|
2900
|
+
else:
|
|
2901
|
+
line = Line[float](_py21c_f32(basepoint),_py21c_f32(direction))
|
|
2902
|
+
self.truc.push_to(line)
|
|
2903
|
+
return self
|
|
2904
|
+
|
|
2905
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
2906
|
+
"""
|
|
2907
|
+
Computes the persistence on a line L defined by
|
|
2908
|
+
- a basepoint (num_parameters,) array
|
|
2909
|
+
- an optional direction (num_parameters,) array
|
|
2910
|
+
"""
|
|
2911
|
+
self.push_to_line(basepoint,direction)
|
|
2912
|
+
self.truc.compute_persistence()
|
|
2913
|
+
return self.truc.get_barcode()
|
|
2914
|
+
def compute_persistence(self,one_filtration=None):
|
|
2915
|
+
"""
|
|
2916
|
+
Computes the current persistence, or the persistence
|
|
2917
|
+
given by the filtration one_filtration (num_generators,).
|
|
2918
|
+
"""
|
|
2919
|
+
if one_filtration is not None:
|
|
2920
|
+
self.truc.set_one_filtration(one_filtration)
|
|
2921
|
+
self.truc.compute_persistence()
|
|
2922
|
+
# return self.truc.get_barcode()
|
|
2923
|
+
def get_barcode(self):
|
|
2924
|
+
"""
|
|
2925
|
+
Returns the barcode of the current 1d-persistence.
|
|
2926
|
+
"""
|
|
2927
|
+
return self.truc.get_barcode()
|
|
2928
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
2929
|
+
"""
|
|
2930
|
+
Computes the filtration on a line L defined by
|
|
2931
|
+
- a basepoint (num_parameters,) array
|
|
2932
|
+
- an optional direction (num_parameters,) array
|
|
2933
|
+
"""
|
|
2934
|
+
self.push_to_line(basepoint,direction)
|
|
2935
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
2936
|
+
def __len__(self):
|
|
2937
|
+
return self.truc.num_generators()
|
|
2938
|
+
@property
|
|
2939
|
+
def num_generators(self):
|
|
2940
|
+
return self.truc.num_generators()
|
|
2941
|
+
@property
|
|
2942
|
+
def num_parameters(self):
|
|
2943
|
+
return self.truc.num_parameters()
|
|
2944
|
+
def info(self):
|
|
2945
|
+
return self.truc.to_str().decode()
|
|
2946
|
+
def compute_box(self):
|
|
2947
|
+
"""
|
|
2948
|
+
Computes the bounding box of the current persistence.
|
|
2949
|
+
"""
|
|
2950
|
+
cdef pair[Finitely_critical_multi_filtration[float],Finitely_critical_multi_filtration[float]] box = self.truc.get_bounding_box()
|
|
2951
|
+
cdef cnp.ndarray[float, ndim=1] a = _ff21cview_f32(&box.first)
|
|
2952
|
+
cdef cnp.ndarray[float, ndim=1] b = _ff21cview_f32(&box.second)
|
|
2953
|
+
return np.asarray([a,b])
|
|
2954
|
+
def get_filtrations_values(self):
|
|
2955
|
+
"""
|
|
2956
|
+
Returns the current filtration values of the slicer.
|
|
2957
|
+
"""
|
|
2958
|
+
cdef vector[Finitely_critical_multi_filtration[float]] v = self.truc.get_filtration_values()
|
|
2959
|
+
out = _vff21cview_f32(v, copy=True)
|
|
2960
|
+
return np.asarray(out)
|
|
2961
|
+
def get_filtrations(self):
|
|
2962
|
+
return _vff21cview_f32(self.truc.get_filtrations(), copy=True)
|
|
2963
|
+
|
|
2964
|
+
def get_dimensions(self):
|
|
2965
|
+
"""
|
|
2966
|
+
Returns the ordered dimensions of the generators.
|
|
2967
|
+
"""
|
|
2968
|
+
return np.asarray(self.truc.get_dimensions())
|
|
2969
|
+
def get_boundaries(self):
|
|
2970
|
+
"""
|
|
2971
|
+
Returns the boundaries of the generators.
|
|
2972
|
+
"""
|
|
2973
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
2974
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
2975
|
+
"""
|
|
2976
|
+
Squeeze the filtration values on a grid.
|
|
2977
|
+
"""
|
|
2978
|
+
if force and self.is_squeezed:
|
|
2979
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
2980
|
+
if filtration_grid is None:
|
|
2981
|
+
filtration_grid = mpg.compute_grid(
|
|
2982
|
+
self.get_filtrations_values().T,
|
|
2983
|
+
strategy=grid_strategy,
|
|
2984
|
+
resolution=resolution)
|
|
2985
|
+
cdef vector[vector[float]] grid = filtration_grid
|
|
2986
|
+
if inplace or not coordinates:
|
|
2987
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
2988
|
+
self.filtration_grid = filtration_grid
|
|
2989
|
+
else:
|
|
2990
|
+
out = _Slicer0_i32()
|
|
2991
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
2992
|
+
out.filtration_grid = filtration_grid
|
|
2993
|
+
return out
|
|
2994
|
+
return self
|
|
2995
|
+
def minpres(self,
|
|
2996
|
+
int degree = 1,
|
|
2997
|
+
list[int] degrees=[],
|
|
2998
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
2999
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
3000
|
+
bool vineyard=False,
|
|
3001
|
+
id :Optional[str] = None,
|
|
3002
|
+
dtype = np.float32,
|
|
3003
|
+
**minpres_kwargs
|
|
3004
|
+
):
|
|
3005
|
+
"""
|
|
3006
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
3007
|
+
"""
|
|
3008
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
3009
|
+
return new_slicer
|
|
3010
|
+
|
|
3011
|
+
@property
|
|
3012
|
+
def dtype(self)->type:
|
|
3013
|
+
return np.float32
|
|
3014
|
+
@property
|
|
3015
|
+
def col_type(self)->str:
|
|
3016
|
+
return "INTRUSIVE_SET"
|
|
3017
|
+
@property
|
|
3018
|
+
def is_vine(self)->bool:
|
|
3019
|
+
return False
|
|
3020
|
+
@property
|
|
3021
|
+
def is_kcritical(self)->bool:
|
|
3022
|
+
return False
|
|
3023
|
+
|
|
3024
|
+
|
|
3025
|
+
|
|
3026
|
+
@staticmethod
|
|
3027
|
+
def from_bitmap(self):
|
|
3028
|
+
raise ValueError("Not implemented.")
|
|
3029
|
+
|
|
3030
|
+
#------------------------------------------------------------------------------
|
|
3031
|
+
cdef class _Slicer0_f64:
|
|
3032
|
+
cdef C_Slicer0_f64 truc
|
|
3033
|
+
cdef public vector[vector[double]] filtration_grid
|
|
3034
|
+
@property
|
|
3035
|
+
def is_squeezed(self)->bool:
|
|
3036
|
+
return self.filtration_grid.size() > 0 and self.filtration_grid[0].size() > 0
|
|
3037
|
+
|
|
3038
|
+
def get_ptr(self):
|
|
3039
|
+
"""
|
|
3040
|
+
Returns a pointer to the underlying C++ slicer.
|
|
3041
|
+
"""
|
|
3042
|
+
return <intptr_t>(&self.truc)
|
|
3043
|
+
def __init__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
3044
|
+
"""
|
|
3045
|
+
Constructs a slicer from
|
|
3046
|
+
- generator maps (Iterable of list of ints)
|
|
3047
|
+
- generator dimensions (Iterable of int)
|
|
3048
|
+
- filtration values (Iterable of filtration values)
|
|
3049
|
+
"""
|
|
3050
|
+
pass
|
|
3051
|
+
def __cinit__(self, generator_maps=[], generator_dimensions=[], filtration_values=[]):
|
|
3052
|
+
"""
|
|
3053
|
+
Cython constructor
|
|
3054
|
+
"""
|
|
3055
|
+
cdef uint32_t num_generators = len(generator_maps)
|
|
3056
|
+
cdef vector[vector[uint32_t]] c_generator_maps
|
|
3057
|
+
cdef vector[Finitely_critical_multi_filtration[double]] c_filtration_values
|
|
3058
|
+
for stuff in generator_maps:
|
|
3059
|
+
c_generator_maps.push_back(<vector[uint32_t]>(stuff))
|
|
3060
|
+
for f in filtration_values:
|
|
3061
|
+
# cf.clear()
|
|
3062
|
+
# for truc in f:
|
|
3063
|
+
# cf.push_back(truc)
|
|
3064
|
+
c_filtration_values.push_back(_py21c_f64(f))
|
|
3065
|
+
cdef vector[int] c_generator_dimensions = generator_dimensions
|
|
3066
|
+
assert num_generators == c_generator_maps.size() == c_filtration_values.size(), "Invalid input, shape do not coincide."
|
|
3067
|
+
self.truc = C_Slicer0_f64(c_generator_maps,c_generator_dimensions, c_filtration_values)
|
|
3068
|
+
def copy(self):
|
|
3069
|
+
"""
|
|
3070
|
+
Returns a copy of the slicer.
|
|
3071
|
+
"""
|
|
3072
|
+
copy_ = _Slicer0_f64()
|
|
3073
|
+
copy_.truc = self.truc
|
|
3074
|
+
return copy_
|
|
3075
|
+
def get_barcode(self):
|
|
3076
|
+
"""
|
|
3077
|
+
Returns the current barcode.
|
|
3078
|
+
"""
|
|
3079
|
+
return self.truc.get_barcode()
|
|
3080
|
+
def push_to_line(self, basepoint, direction=None):
|
|
3081
|
+
"""
|
|
3082
|
+
Pushes the current slicer to the line
|
|
3083
|
+
"""
|
|
3084
|
+
cdef Line[double] line
|
|
3085
|
+
if direction is None:
|
|
3086
|
+
line = Line[double](_py21c_f64(basepoint))
|
|
3087
|
+
else:
|
|
3088
|
+
line = Line[double](_py21c_f64(basepoint),_py21c_f64(direction))
|
|
3089
|
+
self.truc.push_to(line)
|
|
3090
|
+
return self
|
|
3091
|
+
|
|
3092
|
+
def persistence_on_line(self,basepoint,direction=None):
|
|
3093
|
+
"""
|
|
3094
|
+
Computes the persistence on a line L defined by
|
|
3095
|
+
- a basepoint (num_parameters,) array
|
|
3096
|
+
- an optional direction (num_parameters,) array
|
|
3097
|
+
"""
|
|
3098
|
+
self.push_to_line(basepoint,direction)
|
|
3099
|
+
self.truc.compute_persistence()
|
|
3100
|
+
return self.truc.get_barcode()
|
|
3101
|
+
def compute_persistence(self,one_filtration=None):
|
|
3102
|
+
"""
|
|
3103
|
+
Computes the current persistence, or the persistence
|
|
3104
|
+
given by the filtration one_filtration (num_generators,).
|
|
3105
|
+
"""
|
|
3106
|
+
if one_filtration is not None:
|
|
3107
|
+
self.truc.set_one_filtration(one_filtration)
|
|
3108
|
+
self.truc.compute_persistence()
|
|
3109
|
+
# return self.truc.get_barcode()
|
|
3110
|
+
def get_barcode(self):
|
|
3111
|
+
"""
|
|
3112
|
+
Returns the barcode of the current 1d-persistence.
|
|
3113
|
+
"""
|
|
3114
|
+
return self.truc.get_barcode()
|
|
3115
|
+
def sliced_filtration(self,basepoint, direction=None):
|
|
3116
|
+
"""
|
|
3117
|
+
Computes the filtration on a line L defined by
|
|
3118
|
+
- a basepoint (num_parameters,) array
|
|
3119
|
+
- an optional direction (num_parameters,) array
|
|
3120
|
+
"""
|
|
3121
|
+
self.push_to_line(basepoint,direction)
|
|
3122
|
+
return np.asarray(self.truc.get_one_filtration())
|
|
3123
|
+
def __len__(self):
|
|
3124
|
+
return self.truc.num_generators()
|
|
3125
|
+
@property
|
|
3126
|
+
def num_generators(self):
|
|
3127
|
+
return self.truc.num_generators()
|
|
3128
|
+
@property
|
|
3129
|
+
def num_parameters(self):
|
|
3130
|
+
return self.truc.num_parameters()
|
|
3131
|
+
def info(self):
|
|
3132
|
+
return self.truc.to_str().decode()
|
|
3133
|
+
def compute_box(self):
|
|
3134
|
+
"""
|
|
3135
|
+
Computes the bounding box of the current persistence.
|
|
3136
|
+
"""
|
|
3137
|
+
cdef pair[Finitely_critical_multi_filtration[double],Finitely_critical_multi_filtration[double]] box = self.truc.get_bounding_box()
|
|
3138
|
+
cdef cnp.ndarray[double, ndim=1] a = _ff21cview_f64(&box.first)
|
|
3139
|
+
cdef cnp.ndarray[double, ndim=1] b = _ff21cview_f64(&box.second)
|
|
3140
|
+
return np.asarray([a,b])
|
|
3141
|
+
def get_filtrations_values(self):
|
|
3142
|
+
"""
|
|
3143
|
+
Returns the current filtration values of the slicer.
|
|
3144
|
+
"""
|
|
3145
|
+
cdef vector[Finitely_critical_multi_filtration[double]] v = self.truc.get_filtration_values()
|
|
3146
|
+
out = _vff21cview_f64(v, copy=True)
|
|
3147
|
+
return np.asarray(out)
|
|
3148
|
+
def get_filtrations(self):
|
|
3149
|
+
return _vff21cview_f64(self.truc.get_filtrations(), copy=True)
|
|
3150
|
+
|
|
3151
|
+
def get_dimensions(self):
|
|
3152
|
+
"""
|
|
3153
|
+
Returns the ordered dimensions of the generators.
|
|
3154
|
+
"""
|
|
3155
|
+
return np.asarray(self.truc.get_dimensions())
|
|
3156
|
+
def get_boundaries(self):
|
|
3157
|
+
"""
|
|
3158
|
+
Returns the boundaries of the generators.
|
|
3159
|
+
"""
|
|
3160
|
+
return tuple(tuple(b) for b in self.truc.get_boundaries())
|
|
3161
|
+
def grid_squeeze(self, filtration_grid=None, grid_strategy="exact", resolution=-1, bool coordinates=True, bool inplace = False, bool force=False):
|
|
3162
|
+
"""
|
|
3163
|
+
Squeeze the filtration values on a grid.
|
|
3164
|
+
"""
|
|
3165
|
+
if force and self.is_squeezed:
|
|
3166
|
+
raise ValueError("The slicer seems to be already squeezed. Use force=True to resqueeze.")
|
|
3167
|
+
if filtration_grid is None:
|
|
3168
|
+
filtration_grid = mpg.compute_grid(
|
|
3169
|
+
self.get_filtrations_values().T,
|
|
3170
|
+
strategy=grid_strategy,
|
|
3171
|
+
resolution=resolution)
|
|
3172
|
+
cdef vector[vector[double]] grid = filtration_grid
|
|
3173
|
+
if inplace or not coordinates:
|
|
3174
|
+
self.truc.coarsen_on_grid_inplace(grid, coordinates)
|
|
3175
|
+
self.filtration_grid = filtration_grid
|
|
3176
|
+
else:
|
|
3177
|
+
out = _Slicer0_i32()
|
|
3178
|
+
out.truc = self.truc.coarsen_on_grid(grid)
|
|
3179
|
+
out.filtration_grid = filtration_grid
|
|
3180
|
+
return out
|
|
3181
|
+
return self
|
|
3182
|
+
def minpres(self,
|
|
3183
|
+
int degree = 1,
|
|
3184
|
+
list[int] degrees=[],
|
|
3185
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
3186
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
3187
|
+
bool vineyard=False,
|
|
3188
|
+
id :Optional[str] = None,
|
|
3189
|
+
dtype = np.float64,
|
|
3190
|
+
**minpres_kwargs
|
|
3191
|
+
):
|
|
3192
|
+
"""
|
|
3193
|
+
Computes the minimal presentation of the slicer, and returns it as a new slicer.
|
|
3194
|
+
"""
|
|
3195
|
+
new_slicer = minimal_presentation(self, degree=degree, degrees=degrees, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs)
|
|
3196
|
+
return new_slicer
|
|
3197
|
+
|
|
3198
|
+
@property
|
|
3199
|
+
def dtype(self)->type:
|
|
3200
|
+
return np.float64
|
|
3201
|
+
@property
|
|
3202
|
+
def col_type(self)->str:
|
|
3203
|
+
return "INTRUSIVE_SET"
|
|
3204
|
+
@property
|
|
3205
|
+
def is_vine(self)->bool:
|
|
3206
|
+
return False
|
|
3207
|
+
@property
|
|
3208
|
+
def is_kcritical(self)->bool:
|
|
3209
|
+
return False
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
|
|
3213
|
+
@staticmethod
|
|
3214
|
+
def from_bitmap(self):
|
|
3215
|
+
raise ValueError("Not implemented.")
|
|
3216
|
+
|
|
3217
|
+
|
|
3218
|
+
def from_function_delaunay(
|
|
3219
|
+
points,
|
|
3220
|
+
grades,
|
|
3221
|
+
int degree=-1,
|
|
3222
|
+
str backend: Literal["matrix", "clement"] = "matrix",
|
|
3223
|
+
bool vineyard=True,
|
|
3224
|
+
bool verbose = False,
|
|
3225
|
+
bool clear = True,
|
|
3226
|
+
):
|
|
3227
|
+
"""
|
|
3228
|
+
Given points in $\mathbb R^n$ and function grades, compute the function-delaunay
|
|
3229
|
+
bifiltration as a in an scc format, and converts it into a slicer.
|
|
3230
|
+
|
|
3231
|
+
points : (num_pts, n) float array
|
|
3232
|
+
grades : (num_pts,) float array
|
|
3233
|
+
degree (opt) : if given, computes a minimal presentation of this homological degree first
|
|
3234
|
+
backend : slicer backend, e.g. "matrix", "clement"
|
|
3235
|
+
vineyard : bool, use a vineyard-compatible backend
|
|
3236
|
+
"""
|
|
3237
|
+
blocks = mio.function_delaunay_presentation(points, grades, degree=degree, verbose=verbose,clear=clear)
|
|
3238
|
+
return multipers.Slicer(blocks, backend=backend, vineyard=vineyard)
|
|
3239
|
+
|
|
3240
|
+
def slicer2blocks(slicer, int degree = -1, bool reverse=True):
|
|
3241
|
+
"""
|
|
3242
|
+
Convert any slicer to the block format a.k.a. scc format for python
|
|
3243
|
+
"""
|
|
3244
|
+
dims = slicer.get_dimensions()
|
|
3245
|
+
num_empty_blocks_to_add = 1 if degree == -1 else dims.min()-degree +1
|
|
3246
|
+
_,counts = np.unique(dims, return_counts=True, )
|
|
3247
|
+
indices = np.concatenate([[0],counts], dtype=np.int32).cumsum()
|
|
3248
|
+
filtration_values = slicer.get_filtrations()
|
|
3249
|
+
filtration_values = [filtration_values[indices[i]:indices[i+1]] for i in range(len(indices)-1)]
|
|
3250
|
+
boundaries = slicer.get_boundaries()
|
|
3251
|
+
boundaries = [boundaries[indices[i]:indices[i+1]] for i in range(len(indices)-1)]
|
|
3252
|
+
shift = np.concatenate([[0], indices], dtype=np.int32)
|
|
3253
|
+
boundaries = [tuple(np.asarray(x-s, dtype=np.int32) for x in block) for s,block in zip(shift,boundaries)]
|
|
3254
|
+
blocks = [tuple((f,tuple(b))) for b,f in zip(boundaries,filtration_values)]
|
|
3255
|
+
blocks = ([(np.empty((0,)),[])]*num_empty_blocks_to_add) + blocks
|
|
3256
|
+
if reverse:
|
|
3257
|
+
blocks.reverse()
|
|
3258
|
+
return blocks
|
|
3259
|
+
|
|
3260
|
+
def minimal_presentation(
|
|
3261
|
+
slicer,
|
|
3262
|
+
int degree = 1,
|
|
3263
|
+
list[int] degrees=[],
|
|
3264
|
+
str backend:Literal["mpfree", "2pac"]="mpfree",
|
|
3265
|
+
str slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
3266
|
+
bool vineyard=True,
|
|
3267
|
+
id :Optional[str] =None,
|
|
3268
|
+
dtype=None,
|
|
3269
|
+
**minpres_kwargs
|
|
3270
|
+
):
|
|
3271
|
+
"""
|
|
3272
|
+
Computes a minimal presentation of the multifiltered complex given by the slicer,
|
|
3273
|
+
and returns it as a slicer.
|
|
3274
|
+
Only works for mpfree for the moment.
|
|
3275
|
+
"""
|
|
3276
|
+
if len(degrees)>0:
|
|
3277
|
+
return tuple(minimal_presentation(slicer, degree=d, backend=backend, slicer_backend=slicer_backend, vineyard=vineyard, id=id, **minpres_kwargs) for d in degrees)
|
|
3278
|
+
filtration_grid = slicer.filtration_grid if slicer.is_squeezed else None
|
|
3279
|
+
blocks = to_blocks(slicer)
|
|
3280
|
+
if id is None:
|
|
3281
|
+
id = str(threading.get_native_id())
|
|
3282
|
+
if dtype is None:
|
|
3283
|
+
dtype = slicer.dtype
|
|
3284
|
+
mio._init_external_softwares(requires=[backend])
|
|
3285
|
+
mio.scc2disk(blocks,path=mio.input_path+id, strip_comments=True)
|
|
3286
|
+
dimension = len(blocks) -2 - degree # latest = L-1, which is empty, -1 for degree 0, -2 for degree 1 etc.
|
|
3287
|
+
new_blocks = mio.scc_reduce_from_str(path=mio.input_path+id,dimension=dimension, backend=backend, **minpres_kwargs)
|
|
3288
|
+
new_slicer = multipers.Slicer(new_blocks,backend=slicer_backend, vineyard=vineyard, dtype=dtype)
|
|
3289
|
+
if filtration_grid is not None:
|
|
3290
|
+
new_slicer.filtration_grid = filtration_grid
|
|
3291
|
+
return new_slicer
|
|
3292
|
+
|
|
3293
|
+
|
|
3294
|
+
def to_simplextree(s:Slicer_type, max_dim:int=-1):
|
|
3295
|
+
"""
|
|
3296
|
+
Turns a --simplicial-- slicer into a simplextree.
|
|
3297
|
+
|
|
3298
|
+
Warning: Won't work for non-simplicial complexes,
|
|
3299
|
+
i.e., complexes $K$ not satisfying
|
|
3300
|
+
$\forall \sigma \in K,\, \mathrm{dim}(\sigma) = |\partial \sigma|-1$
|
|
3301
|
+
"""
|
|
3302
|
+
dims = s.get_dimensions()
|
|
3303
|
+
assert np.all(dims[:-1] <= dims[1:]), "Dims is not sorted."
|
|
3304
|
+
idx = np.searchsorted(dims, np.unique(dims))
|
|
3305
|
+
idx = np.concatenate([idx, [dims.shape[0]]])
|
|
3306
|
+
if max_dim>=0:
|
|
3307
|
+
idx = idx[:max_dim+2]
|
|
3308
|
+
|
|
3309
|
+
cdef vector[vector[int]] boundaries_ = s.get_boundaries()
|
|
3310
|
+
cdef int a
|
|
3311
|
+
cdef int b
|
|
3312
|
+
if len(idx)>2:
|
|
3313
|
+
a = idx[2]
|
|
3314
|
+
b = idx[-1]
|
|
3315
|
+
for i in range(a, b):
|
|
3316
|
+
boundaries_[i] = np.unique(np.concatenate([boundaries_[k] for k in boundaries_[i]]))
|
|
3317
|
+
boundaries = [np.asarray(boundaries_[idx[i]:idx[i+1]]).T for i in range(len(idx)-1)]
|
|
3318
|
+
boundaries[0] = np.arange(boundaries[0].shape[1])[None,:]
|
|
3319
|
+
filtrations = s.get_filtrations()
|
|
3320
|
+
num_parameters = s.num_parameters
|
|
3321
|
+
filtrations=tuple(filtrations[idx[i]:idx[i+1]] for i in range(len(idx)-1)) # TODO : optimize ?
|
|
3322
|
+
st = SimplexTreeMulti(num_parameters = num_parameters, dtype = s.dtype)
|
|
3323
|
+
for i in range(len(filtrations)):
|
|
3324
|
+
if s.is_kcritical:
|
|
3325
|
+
for f in filtrations[i]:
|
|
3326
|
+
st.insert(np.asarray(boundaries[i], dtype = np.int32),np.asarray(f, dtype=s.dtype))
|
|
3327
|
+
else:
|
|
3328
|
+
st.insert_batch(np.asarray(boundaries[i], dtype= np.int32),np.asarray(filtrations[i], dtype=s.dtype))
|
|
3329
|
+
return st
|
|
3330
|
+
|
|
3331
|
+
|
|
3332
|
+
def is_slicer(object input)->bool:
|
|
3333
|
+
return (False
|
|
3334
|
+
or isinstance(input, _SlicerClement)
|
|
3335
|
+
or isinstance(input, _SlicerVineGraph)
|
|
3336
|
+
or isinstance(input, _SlicerVineSimplicial)
|
|
3337
|
+
or isinstance(input, _SlicerNoVineSimplicial)
|
|
3338
|
+
or isinstance(input, _KSlicer0_vine_i32)
|
|
3339
|
+
or isinstance(input, _KSlicer0_vine_f32)
|
|
3340
|
+
or isinstance(input, _KSlicer0_vine_f64)
|
|
3341
|
+
or isinstance(input, _Slicer0_vine_i32)
|
|
3342
|
+
or isinstance(input, _Slicer0_vine_f32)
|
|
3343
|
+
or isinstance(input, _Slicer0_vine_f64)
|
|
3344
|
+
or isinstance(input, _KSlicer0_i32)
|
|
3345
|
+
or isinstance(input, _KSlicer0_f32)
|
|
3346
|
+
or isinstance(input, _KSlicer0_f64)
|
|
3347
|
+
or isinstance(input, _Slicer0_i32)
|
|
3348
|
+
or isinstance(input, _Slicer0_f32)
|
|
3349
|
+
or isinstance(input, _Slicer0_f64)
|
|
3350
|
+
)
|
|
3351
|
+
|
|
3352
|
+
|
|
3353
|
+
def to_blocks(input):
|
|
3354
|
+
"""
|
|
3355
|
+
Converts input to blocks, if possible.
|
|
3356
|
+
"""
|
|
3357
|
+
if is_slicer(input):
|
|
3358
|
+
return slicer2blocks(input)
|
|
3359
|
+
if isinstance(input, list) or isinstance(input, tuple):
|
|
3360
|
+
return input
|
|
3361
|
+
if isinstance(input, multipers.simplex_tree_multi.SimplexTreeMulti):
|
|
3362
|
+
return mio.simplextree2scc(input)
|
|
3363
|
+
if isinstance(input, str) or isinstance(input, os.PathLike):
|
|
3364
|
+
return mio.scc_parser(input)
|
|
3365
|
+
raise ValueError("Input cannot be converted to blocks.")
|
|
3366
|
+
|
|
3367
|
+
|
|
3368
|
+
|
|
3369
|
+
cdef dict[tuple[bool,bool,type],object] slicer_dict = {
|
|
3370
|
+
(True, False, np.dtype(np.float32), ""): _SlicerClement,
|
|
3371
|
+
(True, True, np.dtype(np.int32), "INTRUSIVE_SET"): _KSlicer0_vine_i32,
|
|
3372
|
+
(True, True, np.dtype(np.float32), "INTRUSIVE_SET"): _KSlicer0_vine_f32,
|
|
3373
|
+
(True, True, np.dtype(np.float64), "INTRUSIVE_SET"): _KSlicer0_vine_f64,
|
|
3374
|
+
(True, False, np.dtype(np.int32), "INTRUSIVE_SET"): _Slicer0_vine_i32,
|
|
3375
|
+
(True, False, np.dtype(np.float32), "INTRUSIVE_SET"): _Slicer0_vine_f32,
|
|
3376
|
+
(True, False, np.dtype(np.float64), "INTRUSIVE_SET"): _Slicer0_vine_f64,
|
|
3377
|
+
(False, True, np.dtype(np.int32), "INTRUSIVE_SET"): _KSlicer0_i32,
|
|
3378
|
+
(False, True, np.dtype(np.float32), "INTRUSIVE_SET"): _KSlicer0_f32,
|
|
3379
|
+
(False, True, np.dtype(np.float64), "INTRUSIVE_SET"): _KSlicer0_f64,
|
|
3380
|
+
(False, False, np.dtype(np.int32), "INTRUSIVE_SET"): _Slicer0_i32,
|
|
3381
|
+
(False, False, np.dtype(np.float32), "INTRUSIVE_SET"): _Slicer0_f32,
|
|
3382
|
+
(False, False, np.dtype(np.float64), "INTRUSIVE_SET"): _Slicer0_f64,
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
def get_matrix_slicer(bool is_vineyard, bool is_k_critical, type dtype, str col):
|
|
3386
|
+
slicer = slicer_dict.get((is_vineyard, is_k_critical, np.dtype(dtype), col), None)
|
|
3387
|
+
if slicer is None:
|
|
3388
|
+
raise ValueError(f"Unimplemented combo for Matrix : {is_vineyard=}, {is_k_critical=}, {dtype=}")
|
|
3389
|
+
return slicer
|
|
3390
|
+
|
|
3391
|
+
|
|
3392
|
+
|
|
3393
|
+
|