multipers 2.3.3b6__cp313-cp313-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.16.dylib +0 -0
- multipers/__init__.py +33 -0
- multipers/_signed_measure_meta.py +453 -0
- multipers/_slicer_meta.py +211 -0
- multipers/array_api/__init__.py +45 -0
- multipers/array_api/numpy.py +41 -0
- multipers/array_api/torch.py +58 -0
- multipers/data/MOL2.py +458 -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 +113 -0
- multipers/distances.py +202 -0
- multipers/filtration_conversions.pxd +229 -0
- multipers/filtration_conversions.pxd.tp +84 -0
- multipers/filtrations/__init__.py +18 -0
- multipers/filtrations/density.py +574 -0
- multipers/filtrations/filtrations.py +361 -0
- multipers/filtrations.pxd +224 -0
- multipers/function_rips.cpython-313-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-313-darwin.so +0 -0
- multipers/grids.pyx +433 -0
- multipers/gudhi/Persistence_slices_interface.h +132 -0
- multipers/gudhi/Simplex_tree_interface.h +239 -0
- multipers/gudhi/Simplex_tree_multi_interface.h +551 -0
- multipers/gudhi/cubical_to_boundary.h +59 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
- multipers/gudhi/gudhi/Debug_utils.h +45 -0
- multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
- multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
- multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
- multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
- multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
- multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
- multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
- multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
- multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
- multipers/gudhi/gudhi/Matrix.h +2107 -0
- multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
- multipers/gudhi/gudhi/Multi_persistence/Box.h +174 -0
- multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
- multipers/gudhi/gudhi/Off_reader.h +173 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +1441 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
- multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
- multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
- multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
- multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
- multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
- multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
- multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
- multipers/gudhi/gudhi/Points_off_io.h +171 -0
- multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
- multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
- multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
- multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
- multipers/gudhi/gudhi/Simplex_tree_multi.h +152 -0
- multipers/gudhi/gudhi/distance_functions.h +62 -0
- multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
- multipers/gudhi/gudhi/persistence_interval.h +253 -0
- multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
- multipers/gudhi/gudhi/reader_utils.h +367 -0
- multipers/gudhi/mma_interface_coh.h +256 -0
- multipers/gudhi/mma_interface_h0.h +223 -0
- multipers/gudhi/mma_interface_matrix.h +293 -0
- multipers/gudhi/naive_merge_tree.h +536 -0
- multipers/gudhi/scc_io.h +310 -0
- multipers/gudhi/truc.h +1403 -0
- multipers/io.cpython-313-darwin.so +0 -0
- multipers/io.pyx +644 -0
- multipers/ml/__init__.py +0 -0
- multipers/ml/accuracies.py +90 -0
- multipers/ml/invariants_with_persistable.py +79 -0
- multipers/ml/kernels.py +176 -0
- multipers/ml/mma.py +713 -0
- multipers/ml/one.py +472 -0
- multipers/ml/point_clouds.py +352 -0
- multipers/ml/signed_measures.py +1589 -0
- multipers/ml/sliced_wasserstein.py +461 -0
- multipers/ml/tools.py +113 -0
- multipers/mma_structures.cpython-313-darwin.so +0 -0
- multipers/mma_structures.pxd +128 -0
- multipers/mma_structures.pyx +2786 -0
- multipers/mma_structures.pyx.tp +1094 -0
- multipers/multi_parameter_rank_invariant/diff_helpers.h +84 -0
- multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
- multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
- multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
- multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
- multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
- multipers/multiparameter_edge_collapse.py +41 -0
- multipers/multiparameter_module_approximation/approximation.h +2330 -0
- multipers/multiparameter_module_approximation/combinatory.h +129 -0
- multipers/multiparameter_module_approximation/debug.h +107 -0
- multipers/multiparameter_module_approximation/euler_curves.h +0 -0
- multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
- multipers/multiparameter_module_approximation/heap_column.h +238 -0
- multipers/multiparameter_module_approximation/images.h +79 -0
- multipers/multiparameter_module_approximation/list_column.h +174 -0
- multipers/multiparameter_module_approximation/list_column_2.h +232 -0
- multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
- multipers/multiparameter_module_approximation/set_column.h +135 -0
- multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
- multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
- multipers/multiparameter_module_approximation/utilities.h +403 -0
- multipers/multiparameter_module_approximation/vector_column.h +223 -0
- multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
- multipers/multiparameter_module_approximation/vineyards.h +464 -0
- multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
- multipers/multiparameter_module_approximation.cpython-313-darwin.so +0 -0
- multipers/multiparameter_module_approximation.pyx +235 -0
- multipers/pickle.py +90 -0
- multipers/plots.py +456 -0
- multipers/point_measure.cpython-313-darwin.so +0 -0
- multipers/point_measure.pyx +395 -0
- multipers/simplex_tree_multi.cpython-313-darwin.so +0 -0
- multipers/simplex_tree_multi.pxd +134 -0
- multipers/simplex_tree_multi.pyx +10840 -0
- multipers/simplex_tree_multi.pyx.tp +2009 -0
- multipers/slicer.cpython-313-darwin.so +0 -0
- multipers/slicer.pxd +3034 -0
- multipers/slicer.pxd.tp +234 -0
- multipers/slicer.pyx +20481 -0
- multipers/slicer.pyx.tp +1088 -0
- multipers/tensor/tensor.h +672 -0
- multipers/tensor.pxd +13 -0
- multipers/test.pyx +44 -0
- multipers/tests/__init__.py +62 -0
- multipers/torch/__init__.py +1 -0
- multipers/torch/diff_grids.py +240 -0
- multipers/torch/rips_density.py +310 -0
- multipers-2.3.3b6.dist-info/METADATA +128 -0
- multipers-2.3.3b6.dist-info/RECORD +183 -0
- multipers-2.3.3b6.dist-info/WHEEL +6 -0
- multipers-2.3.3b6.dist-info/licenses/LICENSE +21 -0
- multipers-2.3.3b6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def noisy_annulus(
|
|
5
|
+
n1: int = 1000,
|
|
6
|
+
n2: int = 200,
|
|
7
|
+
r1: float = 1,
|
|
8
|
+
r2: float = 2,
|
|
9
|
+
dim: int = 2,
|
|
10
|
+
center: np.ndarray | list | None = None,
|
|
11
|
+
**kwargs
|
|
12
|
+
) -> np.ndarray:
|
|
13
|
+
"""Generates a noisy annulus dataset.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
r1 : float.
|
|
18
|
+
Lower radius of the annulus.
|
|
19
|
+
r2 : float.
|
|
20
|
+
Upper radius of the annulus.
|
|
21
|
+
n1 : int
|
|
22
|
+
Number of points in the annulus.
|
|
23
|
+
n2 : int
|
|
24
|
+
Number of points in the square.
|
|
25
|
+
dim : int
|
|
26
|
+
Dimension of the annulus.
|
|
27
|
+
center: list or array
|
|
28
|
+
center of the annulus.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
numpy array
|
|
33
|
+
Dataset. size : (n1+n2) x dim
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
theta = np.random.normal(size=(n1, dim))
|
|
37
|
+
theta /= np.linalg.norm(theta, axis=1)[:, None]
|
|
38
|
+
rs = np.sqrt(np.random.uniform(low=r1**2, high=r2**2, size=n1))
|
|
39
|
+
annulus = rs[:, None] * theta
|
|
40
|
+
if center is not None:
|
|
41
|
+
annulus += np.array(center)
|
|
42
|
+
diffuse_noise = np.random.uniform(size=(n2, dim), low=-1.1 * r2, high=1.1 * r2)
|
|
43
|
+
if center is not None:
|
|
44
|
+
diffuse_noise += np.array(center)
|
|
45
|
+
return np.vstack([annulus, diffuse_noise])
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def three_annulus(num_pts: int = 500, num_outliers: int = 500):
|
|
49
|
+
q, r = divmod(num_pts, 3)
|
|
50
|
+
num_pts_1, num_pts_2, num_pts_3 = q, q + (r > 0), q + (r > 1)
|
|
51
|
+
X = np.block(
|
|
52
|
+
[
|
|
53
|
+
[np.random.uniform(low=-2, high=2, size=(num_outliers, 2))],
|
|
54
|
+
[
|
|
55
|
+
np.array(
|
|
56
|
+
noisy_annulus(
|
|
57
|
+
r1=0.6,
|
|
58
|
+
r2=0.9,
|
|
59
|
+
n1=num_pts_1,
|
|
60
|
+
n2=0,
|
|
61
|
+
center=[1, -0.2],
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
np.array(
|
|
67
|
+
noisy_annulus(
|
|
68
|
+
r1=0.4,
|
|
69
|
+
r2=0.55,
|
|
70
|
+
n1=num_pts_2,
|
|
71
|
+
n2=0,
|
|
72
|
+
center=[-1.2, -1],
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
np.array(
|
|
78
|
+
noisy_annulus(
|
|
79
|
+
r1=0.3,
|
|
80
|
+
r2=0.4,
|
|
81
|
+
n1=num_pts_3,
|
|
82
|
+
n2=0,
|
|
83
|
+
center=[-0.7, 1.1],
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
],
|
|
87
|
+
]
|
|
88
|
+
)
|
|
89
|
+
return X
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def orbit(n: int = 1000, r: float = 1.0, x0=[]):
|
|
93
|
+
point_list = []
|
|
94
|
+
if len(x0) != 2:
|
|
95
|
+
x, y = np.random.uniform(size=2)
|
|
96
|
+
else:
|
|
97
|
+
x, y = x0
|
|
98
|
+
point_list.append([x, y])
|
|
99
|
+
for _ in range(n - 1):
|
|
100
|
+
x = (x + r * y * (1 - y)) % 1
|
|
101
|
+
y = (y + r * x * (1 - x)) % 1
|
|
102
|
+
point_list.append([x, y])
|
|
103
|
+
return np.asarray(point_list, dtype=float)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_orbit5k(num_pts=1000, num_data=5000):
|
|
107
|
+
from sklearn.preprocessing import LabelEncoder
|
|
108
|
+
|
|
109
|
+
rs = [2.5, 3.5, 4, 4.1, 4.3]
|
|
110
|
+
labels = np.random.choice(rs, size=num_data, replace=True)
|
|
111
|
+
X = [orbit(n=num_pts, r=r) for r in labels]
|
|
112
|
+
labels = LabelEncoder().fit_transform(labels)
|
|
113
|
+
return X, labels
|
multipers/distances.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import ot
|
|
3
|
+
|
|
4
|
+
from multipers.mma_structures import PyMultiDiagrams_type
|
|
5
|
+
from multipers.multiparameter_module_approximation import PyModule_type
|
|
6
|
+
from multipers.simplex_tree_multi import SimplexTreeMulti_type
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def sm2diff(sm1, sm2, threshold=None):
|
|
10
|
+
pts = sm1[0]
|
|
11
|
+
dtype = pts.dtype
|
|
12
|
+
if isinstance(pts, np.ndarray):
|
|
13
|
+
|
|
14
|
+
def backend_concatenate(a, b):
|
|
15
|
+
return np.concatenate([a, b], axis=0, dtype=dtype)
|
|
16
|
+
|
|
17
|
+
def backend_tensor(x):
|
|
18
|
+
return np.asarray(x, dtype=int)
|
|
19
|
+
|
|
20
|
+
else:
|
|
21
|
+
import torch
|
|
22
|
+
|
|
23
|
+
assert isinstance(pts, torch.Tensor), "Invalid backend. Numpy or torch."
|
|
24
|
+
|
|
25
|
+
def backend_concatenate(a, b):
|
|
26
|
+
return torch.concatenate([a, b], dim=0)
|
|
27
|
+
|
|
28
|
+
def backend_tensor(x):
|
|
29
|
+
return torch.tensor(x).type(torch.int)
|
|
30
|
+
|
|
31
|
+
pts1, w1 = sm1
|
|
32
|
+
pts2, w2 = sm2
|
|
33
|
+
## TODO: optimize this
|
|
34
|
+
pos_indices1 = backend_tensor(
|
|
35
|
+
[i for i, w in enumerate(w1) for _ in range(w) if w > 0]
|
|
36
|
+
)
|
|
37
|
+
pos_indices2 = backend_tensor(
|
|
38
|
+
[i for i, w in enumerate(w2) for _ in range(w) if w > 0]
|
|
39
|
+
)
|
|
40
|
+
neg_indices1 = backend_tensor(
|
|
41
|
+
[i for i, w in enumerate(w1) for _ in range(-w) if w < 0]
|
|
42
|
+
)
|
|
43
|
+
neg_indices2 = backend_tensor(
|
|
44
|
+
[i for i, w in enumerate(w2) for _ in range(-w) if w < 0]
|
|
45
|
+
)
|
|
46
|
+
x = backend_concatenate(pts1[pos_indices1], pts2[neg_indices2])
|
|
47
|
+
y = backend_concatenate(pts1[neg_indices1], pts2[pos_indices2])
|
|
48
|
+
if threshold is not None:
|
|
49
|
+
x[x>threshold]=threshold
|
|
50
|
+
y[y>threshold]=threshold
|
|
51
|
+
return x, y
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def sm_distance(
|
|
55
|
+
sm1: tuple,
|
|
56
|
+
sm2: tuple,
|
|
57
|
+
reg: float = 0,
|
|
58
|
+
reg_m: float = 0,
|
|
59
|
+
numItermax: int = 10000,
|
|
60
|
+
p: float = 1,
|
|
61
|
+
threshold=None,
|
|
62
|
+
):
|
|
63
|
+
"""
|
|
64
|
+
Computes the wasserstein distances between two signed measures,
|
|
65
|
+
of the form
|
|
66
|
+
- (pts,weights)
|
|
67
|
+
with
|
|
68
|
+
- pts : (num_pts, dim) float array
|
|
69
|
+
- weights : (num_pts,) int array
|
|
70
|
+
|
|
71
|
+
Regularisation:
|
|
72
|
+
- sinkhorn if reg != 0
|
|
73
|
+
- sinkhorn unbalanced if reg_m != 0
|
|
74
|
+
"""
|
|
75
|
+
x, y = sm2diff(sm1, sm2, threshold=threshold)
|
|
76
|
+
loss = ot.dist(
|
|
77
|
+
x, y, metric="sqeuclidean", p=p
|
|
78
|
+
) # only euc + sqeuclidian are implemented in pot for the moment with torch backend # TODO : check later
|
|
79
|
+
if isinstance(x, np.ndarray):
|
|
80
|
+
empty_tensor = np.array([]) # uniform weights
|
|
81
|
+
else:
|
|
82
|
+
import torch
|
|
83
|
+
|
|
84
|
+
assert isinstance(x, torch.Tensor), "Unimplemented backend."
|
|
85
|
+
empty_tensor = torch.tensor([]) # uniform weights
|
|
86
|
+
|
|
87
|
+
if reg == 0:
|
|
88
|
+
return ot.lp.emd2(empty_tensor, empty_tensor, M=loss) * len(x)
|
|
89
|
+
if reg_m == 0:
|
|
90
|
+
return ot.sinkhorn2(
|
|
91
|
+
a=empty_tensor, b=empty_tensor, M=loss, reg=reg, numItermax=numItermax
|
|
92
|
+
)
|
|
93
|
+
return ot.sinkhorn_unbalanced2(
|
|
94
|
+
a=empty_tensor,
|
|
95
|
+
b=empty_tensor,
|
|
96
|
+
M=loss,
|
|
97
|
+
reg=reg,
|
|
98
|
+
reg_m=reg_m,
|
|
99
|
+
numItermax=numItermax,
|
|
100
|
+
)
|
|
101
|
+
# return ot.sinkhorn2(a=onesx,b=onesy,M=loss,reg=reg, numItermax=numItermax)
|
|
102
|
+
# return ot.bregman.empirical_sinkhorn2(x,y,reg=reg)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def estimate_matching(b1: PyMultiDiagrams_type, b2: PyMultiDiagrams_type):
|
|
106
|
+
assert len(b1) == len(b2)
|
|
107
|
+
from gudhi.bottleneck import bottleneck_distance
|
|
108
|
+
|
|
109
|
+
def get_bc(b: PyMultiDiagrams_type, i: int) -> np.ndarray:
|
|
110
|
+
temp = b[i].get_points()
|
|
111
|
+
out = (
|
|
112
|
+
np.array(temp)[:, :, 0] if len(temp) > 0 else np.empty((0, 2))
|
|
113
|
+
) # GUDHI FIX
|
|
114
|
+
return out
|
|
115
|
+
|
|
116
|
+
return max(
|
|
117
|
+
(bottleneck_distance(get_bc(b1, i), get_bc(b2, i)) for i in range(len(b1)))
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# Functions to estimate precision
|
|
122
|
+
def estimate_error(
|
|
123
|
+
st: SimplexTreeMulti_type,
|
|
124
|
+
module: PyModule_type,
|
|
125
|
+
degree: int,
|
|
126
|
+
nlines: int = 100,
|
|
127
|
+
verbose: bool = False,
|
|
128
|
+
):
|
|
129
|
+
"""
|
|
130
|
+
Given an MMA SimplexTree and PyModule, estimates the bottleneck distance using barcodes given by gudhi.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
- st:SimplexTree
|
|
135
|
+
The simplextree representing the n-filtered complex. Used to define the gudhi simplextrees on different lines.
|
|
136
|
+
- module:PyModule
|
|
137
|
+
The module on which to estimate approximation error, w.r.t. the original simplextree st.
|
|
138
|
+
- degree:int
|
|
139
|
+
The homology degree to consider
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
- float:The estimation of the matching distance, i.e., the maximum of the sampled bottleneck distances.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
from time import perf_counter
|
|
147
|
+
|
|
148
|
+
parameter = 0
|
|
149
|
+
|
|
150
|
+
def _get_bc_ST(st, basepoint, degree: int):
|
|
151
|
+
"""
|
|
152
|
+
Slices an mma simplextree to a gudhi simplextree, and compute its persistence on the diagonal line crossing the given basepoint.
|
|
153
|
+
"""
|
|
154
|
+
gst = st.project_on_line(
|
|
155
|
+
basepoint=basepoint, parameter=parameter
|
|
156
|
+
) # we consider only the 1rst coordinate (as )
|
|
157
|
+
gst.compute_persistence()
|
|
158
|
+
return gst.persistence_intervals_in_dimension(degree)
|
|
159
|
+
|
|
160
|
+
from gudhi.bottleneck import bottleneck_distance
|
|
161
|
+
|
|
162
|
+
low, high = module.get_box()
|
|
163
|
+
nfiltration = len(low)
|
|
164
|
+
basepoints = np.random.uniform(low=low, high=high, size=(nlines, nfiltration))
|
|
165
|
+
# barcodes from module
|
|
166
|
+
print("Computing mma barcodes...", flush=1, end="") if verbose else None
|
|
167
|
+
time = perf_counter()
|
|
168
|
+
bcs_from_mod = module.barcodes(degree=degree, basepoints=basepoints).get_points()
|
|
169
|
+
print(f"Done. {perf_counter() - time}s.") if verbose else None
|
|
170
|
+
|
|
171
|
+
def clean(dgm):
|
|
172
|
+
return np.array(
|
|
173
|
+
[
|
|
174
|
+
[birth[parameter], death[parameter]]
|
|
175
|
+
for birth, death in dgm
|
|
176
|
+
if len(birth) > 0 and birth[parameter] != np.inf
|
|
177
|
+
]
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
bcs_from_mod = [
|
|
181
|
+
clean(dgm) for dgm in bcs_from_mod
|
|
182
|
+
] # we only consider the 1st coordinate of the barcode
|
|
183
|
+
# Computes gudhi barcodes
|
|
184
|
+
from tqdm import tqdm
|
|
185
|
+
|
|
186
|
+
bcs_from_gudhi = [
|
|
187
|
+
_get_bc_ST(st, basepoint=basepoint, degree=degree)
|
|
188
|
+
for basepoint in tqdm(
|
|
189
|
+
basepoints, disable=not verbose, desc="Computing gudhi barcodes"
|
|
190
|
+
)
|
|
191
|
+
]
|
|
192
|
+
return max(
|
|
193
|
+
(
|
|
194
|
+
bottleneck_distance(a, b)
|
|
195
|
+
for a, b in tqdm(
|
|
196
|
+
zip(bcs_from_mod, bcs_from_gudhi),
|
|
197
|
+
disable=not verbose,
|
|
198
|
+
total=nlines,
|
|
199
|
+
desc="Computing bottleneck distances",
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
|
|
2
|
+
# Python to C++ conversions
|
|
3
|
+
from multipers.filtrations cimport One_critical_filtration,Multi_critical_filtration
|
|
4
|
+
from libcpp.vector cimport vector
|
|
5
|
+
from libcpp cimport bool
|
|
6
|
+
cimport numpy as cnp
|
|
7
|
+
import numpy as np
|
|
8
|
+
from libc.stdint cimport int32_t, int64_t
|
|
9
|
+
from cython.operator cimport dereference
|
|
10
|
+
###### ------------------- PY TO CPP
|
|
11
|
+
#### ----------
|
|
12
|
+
|
|
13
|
+
cdef inline Multi_critical_filtration[int32_t] _py2kc_i32(int32_t[:,:] filtrations) noexcept nogil:
|
|
14
|
+
# cdef int32_t[:,:] filtrations = np.asarray(filtrations_, dtype=np.int32)
|
|
15
|
+
cdef Multi_critical_filtration[int32_t] out
|
|
16
|
+
out.set_num_generators(filtrations.shape[0])
|
|
17
|
+
for i in range(filtrations.shape[0]):
|
|
18
|
+
out[i].resize(filtrations.shape[1])
|
|
19
|
+
for j in range(filtrations.shape[1]):
|
|
20
|
+
out[i][j] = filtrations[i,j]
|
|
21
|
+
out.simplify()
|
|
22
|
+
return out
|
|
23
|
+
|
|
24
|
+
cdef inline One_critical_filtration[int32_t] _py21c_i32(int32_t[:] filtration) noexcept nogil:
|
|
25
|
+
# cdef int32_t[:] filtration = np.asarray(filtration_, dtype=np.int32)
|
|
26
|
+
cdef One_critical_filtration[int32_t] out = One_critical_filtration[int32_t](0)
|
|
27
|
+
out.reserve(len(filtration))
|
|
28
|
+
for i in range(len(filtration)):
|
|
29
|
+
out.push_back(filtration[i])
|
|
30
|
+
return out
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
cdef inline vector[One_critical_filtration[int32_t]] _py2v1c_i32(int32_t[:,:] filtrations) noexcept nogil:
|
|
34
|
+
# cdef int32_t[:,:] filtrations = np.asarray(filtrations_, dtype=np.int32)
|
|
35
|
+
cdef vector[One_critical_filtration[int32_t]] out
|
|
36
|
+
out.reserve(filtrations.shape[0])
|
|
37
|
+
for i in range(filtrations.shape[0]):
|
|
38
|
+
out.push_back(_py21c_i32(filtrations[i,:]))
|
|
39
|
+
return out
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
###### ------------------- CPP to PY
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## CYTHON BUG: using tuples here will cause some weird issues.
|
|
46
|
+
cdef inline _ff21cview_i32(One_critical_filtration[int32_t]* x, bool copy=False, int duplicate=0):
|
|
47
|
+
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
|
|
48
|
+
if copy and duplicate and not dereference(x).is_finite():
|
|
49
|
+
return np.full(shape=duplicate, fill_value=dereference(x)[0])
|
|
50
|
+
cdef int32_t[:] x_view = <int32_t[:num_parameters]>(&(dereference(x)[0]))
|
|
51
|
+
return np.array(x_view) if copy else np.asarray(x_view)
|
|
52
|
+
|
|
53
|
+
cdef inline _ff2kcview_i32(Multi_critical_filtration[int32_t]* x, bool copy=False, int duplicate=0):
|
|
54
|
+
cdef Py_ssize_t k = dereference(x).num_generators()
|
|
55
|
+
return [_ff21cview_i32(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
cdef inline _vff21cview_i32(vector[One_critical_filtration[int32_t]]& x, bool copy = False, int duplicate=0):
|
|
59
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
60
|
+
return [_ff21cview_i32(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
61
|
+
|
|
62
|
+
cdef inline _vff2kcview_i32(vector[Multi_critical_filtration[int32_t]]& x, bool copy = False, int duplicate=0):
|
|
63
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
64
|
+
return [_ff2kcview_i32(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
65
|
+
###### ------------------- PY TO CPP
|
|
66
|
+
#### ----------
|
|
67
|
+
|
|
68
|
+
cdef inline Multi_critical_filtration[int64_t] _py2kc_i64(int64_t[:,:] filtrations) noexcept nogil:
|
|
69
|
+
# cdef int64_t[:,:] filtrations = np.asarray(filtrations_, dtype=np.int64)
|
|
70
|
+
cdef Multi_critical_filtration[int64_t] out
|
|
71
|
+
out.set_num_generators(filtrations.shape[0])
|
|
72
|
+
for i in range(filtrations.shape[0]):
|
|
73
|
+
out[i].resize(filtrations.shape[1])
|
|
74
|
+
for j in range(filtrations.shape[1]):
|
|
75
|
+
out[i][j] = filtrations[i,j]
|
|
76
|
+
out.simplify()
|
|
77
|
+
return out
|
|
78
|
+
|
|
79
|
+
cdef inline One_critical_filtration[int64_t] _py21c_i64(int64_t[:] filtration) noexcept nogil:
|
|
80
|
+
# cdef int64_t[:] filtration = np.asarray(filtration_, dtype=np.int64)
|
|
81
|
+
cdef One_critical_filtration[int64_t] out = One_critical_filtration[int64_t](0)
|
|
82
|
+
out.reserve(len(filtration))
|
|
83
|
+
for i in range(len(filtration)):
|
|
84
|
+
out.push_back(filtration[i])
|
|
85
|
+
return out
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
cdef inline vector[One_critical_filtration[int64_t]] _py2v1c_i64(int64_t[:,:] filtrations) noexcept nogil:
|
|
89
|
+
# cdef int64_t[:,:] filtrations = np.asarray(filtrations_, dtype=np.int64)
|
|
90
|
+
cdef vector[One_critical_filtration[int64_t]] out
|
|
91
|
+
out.reserve(filtrations.shape[0])
|
|
92
|
+
for i in range(filtrations.shape[0]):
|
|
93
|
+
out.push_back(_py21c_i64(filtrations[i,:]))
|
|
94
|
+
return out
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
###### ------------------- CPP to PY
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
## CYTHON BUG: using tuples here will cause some weird issues.
|
|
101
|
+
cdef inline _ff21cview_i64(One_critical_filtration[int64_t]* x, bool copy=False, int duplicate=0):
|
|
102
|
+
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
|
|
103
|
+
if copy and duplicate and not dereference(x).is_finite():
|
|
104
|
+
return np.full(shape=duplicate, fill_value=dereference(x)[0])
|
|
105
|
+
cdef int64_t[:] x_view = <int64_t[:num_parameters]>(&(dereference(x)[0]))
|
|
106
|
+
return np.array(x_view) if copy else np.asarray(x_view)
|
|
107
|
+
|
|
108
|
+
cdef inline _ff2kcview_i64(Multi_critical_filtration[int64_t]* x, bool copy=False, int duplicate=0):
|
|
109
|
+
cdef Py_ssize_t k = dereference(x).num_generators()
|
|
110
|
+
return [_ff21cview_i64(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
cdef inline _vff21cview_i64(vector[One_critical_filtration[int64_t]]& x, bool copy = False, int duplicate=0):
|
|
114
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
115
|
+
return [_ff21cview_i64(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
116
|
+
|
|
117
|
+
cdef inline _vff2kcview_i64(vector[Multi_critical_filtration[int64_t]]& x, bool copy = False, int duplicate=0):
|
|
118
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
119
|
+
return [_ff2kcview_i64(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
120
|
+
###### ------------------- PY TO CPP
|
|
121
|
+
#### ----------
|
|
122
|
+
|
|
123
|
+
cdef inline Multi_critical_filtration[float] _py2kc_f32(float[:,:] filtrations) noexcept nogil:
|
|
124
|
+
# cdef float[:,:] filtrations = np.asarray(filtrations_, dtype=np.float32)
|
|
125
|
+
cdef Multi_critical_filtration[float] out
|
|
126
|
+
out.set_num_generators(filtrations.shape[0])
|
|
127
|
+
for i in range(filtrations.shape[0]):
|
|
128
|
+
out[i].resize(filtrations.shape[1])
|
|
129
|
+
for j in range(filtrations.shape[1]):
|
|
130
|
+
out[i][j] = filtrations[i,j]
|
|
131
|
+
out.simplify()
|
|
132
|
+
return out
|
|
133
|
+
|
|
134
|
+
cdef inline One_critical_filtration[float] _py21c_f32(float[:] filtration) noexcept nogil:
|
|
135
|
+
# cdef float[:] filtration = np.asarray(filtration_, dtype=np.float32)
|
|
136
|
+
cdef One_critical_filtration[float] out = One_critical_filtration[float](0)
|
|
137
|
+
out.reserve(len(filtration))
|
|
138
|
+
for i in range(len(filtration)):
|
|
139
|
+
out.push_back(filtration[i])
|
|
140
|
+
return out
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
cdef inline vector[One_critical_filtration[float]] _py2v1c_f32(float[:,:] filtrations) noexcept nogil:
|
|
144
|
+
# cdef float[:,:] filtrations = np.asarray(filtrations_, dtype=np.float32)
|
|
145
|
+
cdef vector[One_critical_filtration[float]] out
|
|
146
|
+
out.reserve(filtrations.shape[0])
|
|
147
|
+
for i in range(filtrations.shape[0]):
|
|
148
|
+
out.push_back(_py21c_f32(filtrations[i,:]))
|
|
149
|
+
return out
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
###### ------------------- CPP to PY
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
## CYTHON BUG: using tuples here will cause some weird issues.
|
|
156
|
+
cdef inline _ff21cview_f32(One_critical_filtration[float]* x, bool copy=False, int duplicate=0):
|
|
157
|
+
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
|
|
158
|
+
if copy and duplicate and not dereference(x).is_finite():
|
|
159
|
+
return np.full(shape=duplicate, fill_value=dereference(x)[0])
|
|
160
|
+
cdef float[:] x_view = <float[:num_parameters]>(&(dereference(x)[0]))
|
|
161
|
+
return np.array(x_view) if copy else np.asarray(x_view)
|
|
162
|
+
|
|
163
|
+
cdef inline _ff2kcview_f32(Multi_critical_filtration[float]* x, bool copy=False, int duplicate=0):
|
|
164
|
+
cdef Py_ssize_t k = dereference(x).num_generators()
|
|
165
|
+
return [_ff21cview_f32(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
cdef inline _vff21cview_f32(vector[One_critical_filtration[float]]& x, bool copy = False, int duplicate=0):
|
|
169
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
170
|
+
return [_ff21cview_f32(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
171
|
+
|
|
172
|
+
cdef inline _vff2kcview_f32(vector[Multi_critical_filtration[float]]& x, bool copy = False, int duplicate=0):
|
|
173
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
174
|
+
return [_ff2kcview_f32(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
175
|
+
###### ------------------- PY TO CPP
|
|
176
|
+
#### ----------
|
|
177
|
+
|
|
178
|
+
cdef inline Multi_critical_filtration[double] _py2kc_f64(double[:,:] filtrations) noexcept nogil:
|
|
179
|
+
# cdef double[:,:] filtrations = np.asarray(filtrations_, dtype=np.float64)
|
|
180
|
+
cdef Multi_critical_filtration[double] out
|
|
181
|
+
out.set_num_generators(filtrations.shape[0])
|
|
182
|
+
for i in range(filtrations.shape[0]):
|
|
183
|
+
out[i].resize(filtrations.shape[1])
|
|
184
|
+
for j in range(filtrations.shape[1]):
|
|
185
|
+
out[i][j] = filtrations[i,j]
|
|
186
|
+
out.simplify()
|
|
187
|
+
return out
|
|
188
|
+
|
|
189
|
+
cdef inline One_critical_filtration[double] _py21c_f64(double[:] filtration) noexcept nogil:
|
|
190
|
+
# cdef double[:] filtration = np.asarray(filtration_, dtype=np.float64)
|
|
191
|
+
cdef One_critical_filtration[double] out = One_critical_filtration[double](0)
|
|
192
|
+
out.reserve(len(filtration))
|
|
193
|
+
for i in range(len(filtration)):
|
|
194
|
+
out.push_back(filtration[i])
|
|
195
|
+
return out
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
cdef inline vector[One_critical_filtration[double]] _py2v1c_f64(double[:,:] filtrations) noexcept nogil:
|
|
199
|
+
# cdef double[:,:] filtrations = np.asarray(filtrations_, dtype=np.float64)
|
|
200
|
+
cdef vector[One_critical_filtration[double]] out
|
|
201
|
+
out.reserve(filtrations.shape[0])
|
|
202
|
+
for i in range(filtrations.shape[0]):
|
|
203
|
+
out.push_back(_py21c_f64(filtrations[i,:]))
|
|
204
|
+
return out
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
###### ------------------- CPP to PY
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
## CYTHON BUG: using tuples here will cause some weird issues.
|
|
211
|
+
cdef inline _ff21cview_f64(One_critical_filtration[double]* x, bool copy=False, int duplicate=0):
|
|
212
|
+
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
|
|
213
|
+
if copy and duplicate and not dereference(x).is_finite():
|
|
214
|
+
return np.full(shape=duplicate, fill_value=dereference(x)[0])
|
|
215
|
+
cdef double[:] x_view = <double[:num_parameters]>(&(dereference(x)[0]))
|
|
216
|
+
return np.array(x_view) if copy else np.asarray(x_view)
|
|
217
|
+
|
|
218
|
+
cdef inline _ff2kcview_f64(Multi_critical_filtration[double]* x, bool copy=False, int duplicate=0):
|
|
219
|
+
cdef Py_ssize_t k = dereference(x).num_generators()
|
|
220
|
+
return [_ff21cview_f64(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
cdef inline _vff21cview_f64(vector[One_critical_filtration[double]]& x, bool copy = False, int duplicate=0):
|
|
224
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
225
|
+
return [_ff21cview_f64(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
226
|
+
|
|
227
|
+
cdef inline _vff2kcview_f64(vector[Multi_critical_filtration[double]]& x, bool copy = False, int duplicate=0):
|
|
228
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
229
|
+
return [_ff2kcview_f64(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{{py:
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Filtrations conversions between python and C++
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
## Value types : CTYPE, PYTHON_TYPE, short
|
|
8
|
+
value_types = [
|
|
9
|
+
("int32_t", "np.int32", "i32"),
|
|
10
|
+
("int64_t", "np.int64", "i64"),
|
|
11
|
+
("float", "np.float32", "f32"),
|
|
12
|
+
("double", "np.float64", "f64"),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
}}
|
|
16
|
+
|
|
17
|
+
# Python to C++ conversions
|
|
18
|
+
from multipers.filtrations cimport One_critical_filtration,Multi_critical_filtration
|
|
19
|
+
from libcpp.vector cimport vector
|
|
20
|
+
from libcpp cimport bool
|
|
21
|
+
cimport numpy as cnp
|
|
22
|
+
import numpy as np
|
|
23
|
+
from libc.stdint cimport int32_t, int64_t
|
|
24
|
+
from cython.operator cimport dereference
|
|
25
|
+
|
|
26
|
+
{{for CTYPE, PYTYPE, SHORT in value_types}}
|
|
27
|
+
###### ------------------- PY TO CPP
|
|
28
|
+
#### ----------
|
|
29
|
+
|
|
30
|
+
cdef inline Multi_critical_filtration[{{CTYPE}}] _py2kc_{{SHORT}}({{CTYPE}}[:,:] filtrations) noexcept nogil:
|
|
31
|
+
# cdef {{CTYPE}}[:,:] filtrations = np.asarray(filtrations_, dtype={{PYTYPE}})
|
|
32
|
+
cdef Multi_critical_filtration[{{CTYPE}}] out
|
|
33
|
+
out.set_num_generators(filtrations.shape[0])
|
|
34
|
+
for i in range(filtrations.shape[0]):
|
|
35
|
+
out[i].resize(filtrations.shape[1])
|
|
36
|
+
for j in range(filtrations.shape[1]):
|
|
37
|
+
out[i][j] = filtrations[i,j]
|
|
38
|
+
out.simplify()
|
|
39
|
+
return out
|
|
40
|
+
|
|
41
|
+
cdef inline One_critical_filtration[{{CTYPE}}] _py21c_{{SHORT}}({{CTYPE}}[:] filtration) noexcept nogil:
|
|
42
|
+
# cdef {{CTYPE}}[:] filtration = np.asarray(filtration_, dtype={{PYTYPE}})
|
|
43
|
+
cdef One_critical_filtration[{{CTYPE}}] out = One_critical_filtration[{{CTYPE}}](0)
|
|
44
|
+
out.reserve(len(filtration))
|
|
45
|
+
for i in range(len(filtration)):
|
|
46
|
+
out.push_back(filtration[i])
|
|
47
|
+
return out
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
cdef inline vector[One_critical_filtration[{{CTYPE}}]] _py2v1c_{{SHORT}}({{CTYPE}}[:,:] filtrations) noexcept nogil:
|
|
51
|
+
# cdef {{CTYPE}}[:,:] filtrations = np.asarray(filtrations_, dtype={{PYTYPE}})
|
|
52
|
+
cdef vector[One_critical_filtration[{{CTYPE}}]] out
|
|
53
|
+
out.reserve(filtrations.shape[0])
|
|
54
|
+
for i in range(filtrations.shape[0]):
|
|
55
|
+
out.push_back(_py21c_{{SHORT}}(filtrations[i,:]))
|
|
56
|
+
return out
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
###### ------------------- CPP to PY
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## CYTHON BUG: using tuples here will cause some weird issues.
|
|
63
|
+
cdef inline _ff21cview_{{SHORT}}(One_critical_filtration[{{CTYPE}}]* x, bool copy=False, int duplicate=0):
|
|
64
|
+
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
|
|
65
|
+
if copy and duplicate and not dereference(x).is_finite():
|
|
66
|
+
return np.full(shape=duplicate, fill_value=dereference(x)[0])
|
|
67
|
+
cdef {{CTYPE}}[:] x_view = <{{CTYPE}}[:num_parameters]>(&(dereference(x)[0]))
|
|
68
|
+
return np.array(x_view) if copy else np.asarray(x_view)
|
|
69
|
+
|
|
70
|
+
cdef inline _ff2kcview_{{SHORT}}(Multi_critical_filtration[{{CTYPE}}]* x, bool copy=False, int duplicate=0):
|
|
71
|
+
cdef Py_ssize_t k = dereference(x).num_generators()
|
|
72
|
+
return [_ff21cview_{{SHORT}}(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
cdef inline _vff21cview_{{SHORT}}(vector[One_critical_filtration[{{CTYPE}}]]& x, bool copy = False, int duplicate=0):
|
|
76
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
77
|
+
return [_ff21cview_{{SHORT}}(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
78
|
+
|
|
79
|
+
cdef inline _vff2kcview_{{SHORT}}(vector[Multi_critical_filtration[{{CTYPE}}]]& x, bool copy = False, int duplicate=0):
|
|
80
|
+
cdef Py_ssize_t num_stuff = x.size()
|
|
81
|
+
return [_ff2kcview_{{SHORT}}(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]
|
|
82
|
+
|
|
83
|
+
{{endfor}}
|
|
84
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .filtrations import (
|
|
2
|
+
CoreDelaunay,
|
|
3
|
+
Cubical,
|
|
4
|
+
DegreeRips,
|
|
5
|
+
DelaunayCodensity,
|
|
6
|
+
DelaunayLowerstar,
|
|
7
|
+
RipsCodensity,
|
|
8
|
+
RipsLowerstar,
|
|
9
|
+
)
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CoreDelaunay",
|
|
12
|
+
"Cubical",
|
|
13
|
+
"DegreeRips",
|
|
14
|
+
"DelaunayCodensity",
|
|
15
|
+
"DelaunayLowerstar",
|
|
16
|
+
"RipsCodensity",
|
|
17
|
+
"RipsLowerstar",
|
|
18
|
+
]
|