multipers 2.0.0__cp311-cp311-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-311-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-311-darwin.so +0 -0
- multipers/grids.pyx +281 -0
- multipers/hilbert_function.pyi +46 -0
- multipers/hilbert_function.pyx +153 -0
- multipers/io.cpython-311-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-311-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-311-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-311-darwin.so +0 -0
- multipers/point_measure_integration.pyx +139 -0
- multipers/rank_invariant.cpython-311-darwin.so +0 -0
- multipers/rank_invariant.pyx +229 -0
- multipers/simplex_tree_multi.cpython-311-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-311-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-2.0.0.dist-info/LICENSE +21 -0
- multipers-2.0.0.dist-info/METADATA +29 -0
- multipers-2.0.0.dist-info/RECORD +78 -0
- multipers-2.0.0.dist-info/WHEEL +5 -0
- multipers-2.0.0.dist-info/top_level.txt +1 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
multipers/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Doc
|
|
2
|
+
import multipers.io
|
|
3
|
+
import multipers.multiparameter_module_approximation
|
|
4
|
+
import multipers.simplex_tree_multi
|
|
5
|
+
import multipers.slicer
|
|
6
|
+
from multipers._signed_measure_meta import signed_measure
|
|
7
|
+
from multipers._slicer_meta import Slicer
|
|
8
|
+
from multipers.multiparameter_module_approximation import module_approximation
|
|
9
|
+
|
|
10
|
+
# Shortcuts
|
|
11
|
+
from multipers.simplex_tree_multi import SimplexTreeMulti
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from multipers.grids import compute_grid, sms_in_grid
|
|
6
|
+
from multipers.plots import plot_signed_measures
|
|
7
|
+
from multipers.point_measure_integration import clean_sms
|
|
8
|
+
from multipers.rank_invariant import rank_from_slicer
|
|
9
|
+
from multipers.simplex_tree_multi import (
|
|
10
|
+
SimplexTreeMulti_type,
|
|
11
|
+
_available_strategies,
|
|
12
|
+
is_simplextree_multi,
|
|
13
|
+
)
|
|
14
|
+
from multipers.slicer import Slicer_type, is_slicer
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def signed_measure(
|
|
18
|
+
simplextree: Union[SimplexTreeMulti_type, Slicer_type],
|
|
19
|
+
degree: Optional[int] = None,
|
|
20
|
+
degrees=[None],
|
|
21
|
+
mass_default=None,
|
|
22
|
+
grid_strategy: _available_strategies = "exact",
|
|
23
|
+
invariant: Optional[str] = None,
|
|
24
|
+
plot: bool = False,
|
|
25
|
+
verbose: bool = False,
|
|
26
|
+
n_jobs: int = -1,
|
|
27
|
+
expand_collapse: bool = False,
|
|
28
|
+
backend: str = "multipers",
|
|
29
|
+
thread_id: str = "",
|
|
30
|
+
input_path: Optional[str] = None,
|
|
31
|
+
grid_conversion: Optional[list] = None,
|
|
32
|
+
coordinate_measure: bool = False,
|
|
33
|
+
num_collapses: int = 0,
|
|
34
|
+
clean: bool = False,
|
|
35
|
+
**infer_grid_kwargs,
|
|
36
|
+
) -> list[tuple[np.ndarray, np.ndarray]]:
|
|
37
|
+
"""
|
|
38
|
+
Computes the signed measures given by the decomposition of the hilbert
|
|
39
|
+
function or the euler characteristic.
|
|
40
|
+
|
|
41
|
+
Input
|
|
42
|
+
-----
|
|
43
|
+
- simplextree:SimplexTreeMulti, the multifiltered simplicial complex.
|
|
44
|
+
Its recommended to squeeze the simplextree first.
|
|
45
|
+
- mass_default: Either None, or 'auto' or 'inf', or array-like of floats.
|
|
46
|
+
Where to put the default mass to get a zero-mass measure.
|
|
47
|
+
- degree:int|None / degrees:list[int] the degrees to compute.
|
|
48
|
+
None represents the euler characteristic.
|
|
49
|
+
- plot:bool, plots the computed measures if true.
|
|
50
|
+
- n_jobs:int, number of jobs.
|
|
51
|
+
Defaults to #cpu, but when doing parallel computations of signed measures, we recommend setting this to 1.
|
|
52
|
+
- verbose:bool, prints c++ logs.
|
|
53
|
+
|
|
54
|
+
Output
|
|
55
|
+
------
|
|
56
|
+
`[signed_measure_of_degree for degree in degrees]`
|
|
57
|
+
with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
|
|
58
|
+
"""
|
|
59
|
+
if len(degrees) == 1 and degrees[0] is None and degree is not None:
|
|
60
|
+
degrees = [degree]
|
|
61
|
+
if None in degrees:
|
|
62
|
+
assert len(degrees) == 1
|
|
63
|
+
if len(degrees) == 0:
|
|
64
|
+
return []
|
|
65
|
+
if is_slicer(simplextree):
|
|
66
|
+
if grid_conversion is None and not simplextree.is_squeezed:
|
|
67
|
+
grid_conversion = compute_grid(
|
|
68
|
+
simplextree.get_filtrations_values().T,
|
|
69
|
+
strategy=grid_strategy,
|
|
70
|
+
**infer_grid_kwargs,
|
|
71
|
+
)
|
|
72
|
+
if not simplextree.is_squeezed:
|
|
73
|
+
simplextree_ = simplextree.grid_squeeze(grid_conversion, coordinates=True)
|
|
74
|
+
else:
|
|
75
|
+
simplextree_ = simplextree
|
|
76
|
+
if grid_conversion is None:
|
|
77
|
+
grid_conversion = tuple(
|
|
78
|
+
np.asarray(f, dtype=np.float64) for f in simplextree.filtration_grid
|
|
79
|
+
)
|
|
80
|
+
if invariant == "rank": # TODO Hilbert from slicer
|
|
81
|
+
degrees = np.asarray(degrees, dtype=int)
|
|
82
|
+
return rank_from_slicer(
|
|
83
|
+
simplextree_,
|
|
84
|
+
degrees=degrees,
|
|
85
|
+
n_jobs=n_jobs,
|
|
86
|
+
grid_shape=tuple(len(g) for g in grid_conversion),
|
|
87
|
+
grid_conversion=grid_conversion,
|
|
88
|
+
plot=plot,
|
|
89
|
+
)
|
|
90
|
+
return _signed_measure_from_slicer(
|
|
91
|
+
simplextree_,
|
|
92
|
+
plot=plot,
|
|
93
|
+
grid_conversion=grid_conversion,
|
|
94
|
+
clean=clean,
|
|
95
|
+
)
|
|
96
|
+
assert is_simplextree_multi(simplextree), "Input has to be simplextree or slicer."
|
|
97
|
+
assert invariant is None or invariant in [
|
|
98
|
+
"hilbert",
|
|
99
|
+
"rank_invariant",
|
|
100
|
+
"euler",
|
|
101
|
+
"rank",
|
|
102
|
+
"euler_characteristic",
|
|
103
|
+
"hilbert_function",
|
|
104
|
+
]
|
|
105
|
+
assert not plot or simplextree.num_parameters == 2, "Can only plot 2d measures."
|
|
106
|
+
|
|
107
|
+
if not simplextree._is_squeezed:
|
|
108
|
+
if grid_conversion is None:
|
|
109
|
+
grid_conversion = simplextree.get_filtration_grid(
|
|
110
|
+
grid_strategy=grid_strategy,
|
|
111
|
+
**infer_grid_kwargs,
|
|
112
|
+
) # put a warning ?
|
|
113
|
+
simplextree_ = simplextree.grid_squeeze(
|
|
114
|
+
grid_conversion,
|
|
115
|
+
coordinate_values=True,
|
|
116
|
+
inplace=False,
|
|
117
|
+
**infer_grid_kwargs,
|
|
118
|
+
)
|
|
119
|
+
if num_collapses != 0:
|
|
120
|
+
simplextree_.collapse_edges(num_collapses)
|
|
121
|
+
else:
|
|
122
|
+
simplextree_ = simplextree
|
|
123
|
+
if grid_conversion is None:
|
|
124
|
+
grid_conversion = [np.asarray(f) for f in simplextree_.filtration_grid]
|
|
125
|
+
if coordinate_measure:
|
|
126
|
+
grid_conversion = None
|
|
127
|
+
|
|
128
|
+
if backend != "multipers":
|
|
129
|
+
if input_path is not None:
|
|
130
|
+
import multipers.io as mio
|
|
131
|
+
|
|
132
|
+
mio.input_path = input_path
|
|
133
|
+
assert (
|
|
134
|
+
len(degrees) == 1
|
|
135
|
+
and mass_default is None
|
|
136
|
+
and (invariant is None or "hilbert" in invariant)
|
|
137
|
+
)
|
|
138
|
+
from multipers.io import reduce_complex
|
|
139
|
+
|
|
140
|
+
minimal_presentation = reduce_complex(
|
|
141
|
+
simplextree_,
|
|
142
|
+
full_resolution=True,
|
|
143
|
+
dimension=degrees[0],
|
|
144
|
+
id=thread_id,
|
|
145
|
+
backend=backend,
|
|
146
|
+
verbose=verbose,
|
|
147
|
+
)
|
|
148
|
+
sms = _signed_measure_from_scc(
|
|
149
|
+
minimal_presentation, grid_conversion=grid_conversion
|
|
150
|
+
)
|
|
151
|
+
if plot:
|
|
152
|
+
from multipers.plots import plot_signed_measures
|
|
153
|
+
|
|
154
|
+
plot_signed_measures(sms)
|
|
155
|
+
return sms
|
|
156
|
+
# assert simplextree.num_parameters == 2
|
|
157
|
+
if mass_default is None:
|
|
158
|
+
mass_default = mass_default
|
|
159
|
+
elif mass_default == "inf":
|
|
160
|
+
mass_default = np.array([np.inf] * simplextree.num_parameters)
|
|
161
|
+
elif mass_default == "auto":
|
|
162
|
+
grid_conversion = [np.asarray(f) for f in simplextree_.filtration_grid]
|
|
163
|
+
mass_default = np.array(
|
|
164
|
+
[1.1 * np.max(f) - 0.1 * np.min(f) for f in grid_conversion]
|
|
165
|
+
)
|
|
166
|
+
else:
|
|
167
|
+
mass_default = np.asarray(mass_default)
|
|
168
|
+
assert (
|
|
169
|
+
mass_default.ndim == 1
|
|
170
|
+
and mass_default.shape[0] == simplextree.num_parameters
|
|
171
|
+
)
|
|
172
|
+
# assert not coordinate_measure or grid_conversion is None
|
|
173
|
+
|
|
174
|
+
if invariant in ["rank_invariant", "rank"]:
|
|
175
|
+
assert (
|
|
176
|
+
simplextree.num_parameters == 2
|
|
177
|
+
), "Rank invariant only implemented for 2-parameter modules."
|
|
178
|
+
assert not coordinate_measure, "Not implemented"
|
|
179
|
+
from multipers.simplex_tree_multi import _rank_signed_measure as smri
|
|
180
|
+
|
|
181
|
+
sms = smri(
|
|
182
|
+
simplextree_,
|
|
183
|
+
mass_default=mass_default,
|
|
184
|
+
degrees=degrees,
|
|
185
|
+
plot=plot,
|
|
186
|
+
expand_collapse=expand_collapse,
|
|
187
|
+
)
|
|
188
|
+
elif len(degrees) == 1 and degrees[0] is None:
|
|
189
|
+
assert invariant is None or invariant in [
|
|
190
|
+
"euler",
|
|
191
|
+
"euler_characteristic",
|
|
192
|
+
], "Provide a degree to compute hilbert function."
|
|
193
|
+
# assert not coordinate_measure, "Not implemented"
|
|
194
|
+
from multipers.simplex_tree_multi import _euler_signed_measure
|
|
195
|
+
|
|
196
|
+
sms = [
|
|
197
|
+
_euler_signed_measure(
|
|
198
|
+
simplextree_,
|
|
199
|
+
mass_default=mass_default,
|
|
200
|
+
verbose=verbose,
|
|
201
|
+
plot=plot,
|
|
202
|
+
grid_conversion=grid_conversion,
|
|
203
|
+
)
|
|
204
|
+
]
|
|
205
|
+
else:
|
|
206
|
+
assert invariant is None or invariant in [
|
|
207
|
+
"hilbert",
|
|
208
|
+
"hilbert_function",
|
|
209
|
+
], "Found homological degrees for euler computation."
|
|
210
|
+
from multipers.simplex_tree_multi import (
|
|
211
|
+
_hilbert_signed_measure as hilbert_signed_measure,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
sms = hilbert_signed_measure(
|
|
215
|
+
simplextree_,
|
|
216
|
+
degrees=degrees,
|
|
217
|
+
mass_default=mass_default,
|
|
218
|
+
verbose=verbose,
|
|
219
|
+
plot=plot,
|
|
220
|
+
n_jobs=n_jobs,
|
|
221
|
+
expand_collapse=expand_collapse,
|
|
222
|
+
grid_conversion=grid_conversion,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
if clean:
|
|
226
|
+
sms = clean_sms(sms)
|
|
227
|
+
return sms
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _signed_measure_from_scc(
|
|
231
|
+
minimal_presentation, grid_conversion=None
|
|
232
|
+
) -> list[tuple[np.ndarray, np.ndarray]]:
|
|
233
|
+
pts = np.concatenate([b[0] for b in minimal_presentation if len(b[0]) > 0])
|
|
234
|
+
weights = np.concatenate(
|
|
235
|
+
[
|
|
236
|
+
(1 - 2 * (i % 2)) * np.ones(len(b[0]))
|
|
237
|
+
for i, b in enumerate(minimal_presentation)
|
|
238
|
+
]
|
|
239
|
+
)
|
|
240
|
+
sm = [(pts, weights)]
|
|
241
|
+
if grid_conversion is not None:
|
|
242
|
+
sm = sms_in_grid(sm, grid_conversion)
|
|
243
|
+
return sm
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _signed_measure_from_slicer(
|
|
247
|
+
slicer: Slicer_type,
|
|
248
|
+
plot: bool = False,
|
|
249
|
+
grid_conversion=None,
|
|
250
|
+
clean: bool = False,
|
|
251
|
+
) -> list[tuple[np.ndarray, np.ndarray]]:
|
|
252
|
+
pts = slicer.get_filtrations()
|
|
253
|
+
dims = slicer.get_dimensions()
|
|
254
|
+
weights = 1 - 2 * (
|
|
255
|
+
(1 + dims) % 2
|
|
256
|
+
) # dim 0 is always empty : TODO : make that more clean
|
|
257
|
+
sm = [(pts, weights)]
|
|
258
|
+
if slicer.is_squeezed and grid_conversion is None:
|
|
259
|
+
grid_conversion = [
|
|
260
|
+
np.asarray(f, dtype=np.float64) for f in slicer.filtration_grid
|
|
261
|
+
]
|
|
262
|
+
if grid_conversion is not None:
|
|
263
|
+
sm = sms_in_grid(sm, grid_conversion)
|
|
264
|
+
if clean:
|
|
265
|
+
sm = clean_sms(sm)
|
|
266
|
+
if plot:
|
|
267
|
+
plot_signed_measures(sm)
|
|
268
|
+
return sm
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
from typing import Literal, Optional
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
import multipers.io as mio
|
|
7
|
+
import multipers.slicer as mps
|
|
8
|
+
from multipers.simplex_tree_multi import is_simplextree_multi
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## TODO : maybe optimize this with cython
|
|
12
|
+
def _blocks2boundary_dimension_grades(
|
|
13
|
+
blocks,
|
|
14
|
+
filtration_type=np.float64,
|
|
15
|
+
num_parameters: int = -1,
|
|
16
|
+
inplace: bool = False,
|
|
17
|
+
is_kcritical: bool = False,
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
Turns blocks, aka scc, into the input of non-simplicial slicers.
|
|
21
|
+
"""
|
|
22
|
+
if num_parameters < 0:
|
|
23
|
+
for b in blocks:
|
|
24
|
+
if len(b[0]) > 0:
|
|
25
|
+
if is_kcritical:
|
|
26
|
+
num_parameters = np.asarray(b[0][0]).shape[1]
|
|
27
|
+
else:
|
|
28
|
+
num_parameters = np.asarray(b[0]).shape[1]
|
|
29
|
+
break
|
|
30
|
+
if num_parameters < 0:
|
|
31
|
+
raise ValueError("Empty Filtration")
|
|
32
|
+
rblocks = blocks if inplace else deepcopy(blocks)
|
|
33
|
+
rblocks.reverse()
|
|
34
|
+
block_sizes = [len(b[0]) for b in rblocks]
|
|
35
|
+
S = np.cumsum([0, 0] + block_sizes)
|
|
36
|
+
if is_kcritical:
|
|
37
|
+
multifiltration = tuple(
|
|
38
|
+
stuff
|
|
39
|
+
for b in rblocks
|
|
40
|
+
for stuff in (b[0] if len(b[0]) > 0 else [np.empty((0, num_parameters))])
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
else:
|
|
44
|
+
multifiltration = np.concatenate(
|
|
45
|
+
tuple(
|
|
46
|
+
b[0] if len(b[0]) > 0 else np.empty((0, num_parameters))
|
|
47
|
+
for b in rblocks
|
|
48
|
+
),
|
|
49
|
+
dtype=filtration_type,
|
|
50
|
+
)
|
|
51
|
+
boundary = tuple(x + S[i] for i, b in enumerate(rblocks) for x in b[1])
|
|
52
|
+
dimensions = np.fromiter(
|
|
53
|
+
(i for i, b in enumerate(rblocks) for _ in range(len(b[0]))), dtype=int
|
|
54
|
+
)
|
|
55
|
+
return boundary, dimensions, multifiltration
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _slicer_from_simplextree(st, backend, vineyard):
|
|
59
|
+
if vineyard:
|
|
60
|
+
if backend == "matrix":
|
|
61
|
+
slicer = mps._SlicerVineSimplicial(st)
|
|
62
|
+
elif backend == "clement":
|
|
63
|
+
raise ValueError("This one takes a minpres")
|
|
64
|
+
elif backend == "graph":
|
|
65
|
+
slicer = mps._SlicerVineGraph(st)
|
|
66
|
+
else:
|
|
67
|
+
raise ValueError(f"Inimplemented backend {backend}.")
|
|
68
|
+
else:
|
|
69
|
+
if backend == "matrix":
|
|
70
|
+
slicer = mps._SlicerNoVineSimplicial(st)
|
|
71
|
+
if backend == "clement":
|
|
72
|
+
raise ValueError("Clement is Vineyard")
|
|
73
|
+
if backend == "graph":
|
|
74
|
+
raise ValueError("Graph is Vineyard")
|
|
75
|
+
return slicer
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _slicer_from_blocks(
|
|
79
|
+
blocks,
|
|
80
|
+
backend,
|
|
81
|
+
vineyard: bool,
|
|
82
|
+
is_kcritical: bool,
|
|
83
|
+
dtype: type,
|
|
84
|
+
col: str,
|
|
85
|
+
):
|
|
86
|
+
boundary, dimensions, multifiltrations = _blocks2boundary_dimension_grades(
|
|
87
|
+
blocks,
|
|
88
|
+
inplace=False,
|
|
89
|
+
is_kcritical=is_kcritical,
|
|
90
|
+
)
|
|
91
|
+
if backend == "matrix":
|
|
92
|
+
slicer = mps.get_matrix_slicer(vineyard, is_kcritical, dtype, col)(
|
|
93
|
+
boundary, dimensions, multifiltrations
|
|
94
|
+
)
|
|
95
|
+
elif backend == "clement":
|
|
96
|
+
assert dtype == np.float32 and not is_kcritical and vineyard
|
|
97
|
+
slicer = mps._SlicerClement(boundary, dimensions, multifiltrations)
|
|
98
|
+
else:
|
|
99
|
+
raise ValueError(f"Inimplemented backend {backend}.")
|
|
100
|
+
return slicer
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def Slicer(
|
|
104
|
+
st,
|
|
105
|
+
backend: Literal["matrix", "clement", "graph"] = "matrix",
|
|
106
|
+
vineyard: bool = True,
|
|
107
|
+
reduce: bool = False,
|
|
108
|
+
reduce_backend: Optional[str] = None,
|
|
109
|
+
dtype=np.float64,
|
|
110
|
+
is_kcritical: bool = False,
|
|
111
|
+
column_type: str = "INTRUSIVE_SET",
|
|
112
|
+
) -> mps.Slicer_type:
|
|
113
|
+
"""
|
|
114
|
+
Given a simplextree or blocks (a.k.a scc for python),
|
|
115
|
+
returns a structure that can compute persistence on line (or more)
|
|
116
|
+
slices, eventually vineyard update, etc.
|
|
117
|
+
|
|
118
|
+
This can be used to compute interval-decomposable module approximations
|
|
119
|
+
or signed measures, using, e.g.
|
|
120
|
+
- `multipers.module_approximation(this, *args)`
|
|
121
|
+
- `multipers.signed_measure(this, *args)`
|
|
122
|
+
|
|
123
|
+
Note : it is recommended and sometime required to apply
|
|
124
|
+
a minimal presentation before computing these functions !
|
|
125
|
+
`mp.slicer.minimal_presentation(slicer, *args, **kwargs)`
|
|
126
|
+
|
|
127
|
+
Input
|
|
128
|
+
-----
|
|
129
|
+
- st : SimplexTreeMulti or scc-like blocks or path to scc file
|
|
130
|
+
- backend: slicer backend, e.g, "matrix", "clement", "graph"
|
|
131
|
+
- vineyard: vineyard capable (may slow down computations if true)
|
|
132
|
+
Output
|
|
133
|
+
------
|
|
134
|
+
The corresponding slicer.
|
|
135
|
+
"""
|
|
136
|
+
if mps.is_slicer(st):
|
|
137
|
+
slicer = mps.get_matrix_slicer(vineyard, is_kcritical, dtype, column_type)(
|
|
138
|
+
st.get_boundaries(), st.get_dimensions(), st.get_filtrations()
|
|
139
|
+
)
|
|
140
|
+
if st.is_squeezed:
|
|
141
|
+
slicer.filtration_grid = st.filtration_grid
|
|
142
|
+
elif is_simplextree_multi(st) and backend == "graph":
|
|
143
|
+
slicer = _slicer_from_simplextree(st, backend, vineyard)
|
|
144
|
+
if st._is_squeezed:
|
|
145
|
+
slicer.filtration_grid = st.filtration_grid
|
|
146
|
+
elif backend == "graph":
|
|
147
|
+
raise ValueError(
|
|
148
|
+
"""
|
|
149
|
+
Graph is simplicial, incompatible with minpres.
|
|
150
|
+
You can try using `multipers.slicer.to_simplextree`."""
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
filtration_grid = None
|
|
154
|
+
if is_simplextree_multi(st):
|
|
155
|
+
blocks = st._to_scc()
|
|
156
|
+
if st._is_squeezed:
|
|
157
|
+
filtration_grid = st.filtration_grid
|
|
158
|
+
elif isinstance(st, str):
|
|
159
|
+
blocks = mio.scc_parser(st)
|
|
160
|
+
else:
|
|
161
|
+
blocks = st
|
|
162
|
+
slicer = _slicer_from_blocks(
|
|
163
|
+
blocks, backend, vineyard, is_kcritical, dtype, column_type
|
|
164
|
+
)
|
|
165
|
+
if filtration_grid is not None:
|
|
166
|
+
slicer.filtration_grid = filtration_grid
|
|
167
|
+
if reduce:
|
|
168
|
+
slicer = mps.minimal_presentation(
|
|
169
|
+
slicer, backend=reduce_backend, slicer_backend=backend, vineyard=vineyard
|
|
170
|
+
)
|
|
171
|
+
return slicer
|