multipers 2.3.2__cp310-cp310-win_amd64.whl → 2.3.3__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- multipers/_signed_measure_meta.py +22 -8
- multipers/array_api/__init__.py +25 -2
- multipers/array_api/numpy.py +70 -0
- multipers/array_api/torch.py +82 -0
- multipers/filtrations/density.py +11 -52
- multipers/filtrations/filtrations.py +21 -8
- multipers/function_rips.cp310-win_amd64.pyd +0 -0
- multipers/grids.cp310-win_amd64.pyd +0 -0
- multipers/grids.pyx +91 -43
- multipers/gudhi/gudhi/Multi_critical_filtration.h +1 -1
- multipers/io.cp310-win_amd64.pyd +0 -0
- multipers/ml/signed_measures.py +106 -26
- multipers/mma_structures.cp310-win_amd64.pyd +0 -0
- multipers/mma_structures.pyx +2 -2
- multipers/mma_structures.pyx.tp +1 -1
- multipers/multiparameter_module_approximation.cp310-win_amd64.pyd +0 -0
- multipers/plots.py +164 -37
- multipers/point_measure.cp310-win_amd64.pyd +0 -0
- multipers/point_measure.pyx +71 -2
- multipers/simplex_tree_multi.cp310-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.pxd +2 -2
- multipers/simplex_tree_multi.pyx +164 -8
- multipers/simplex_tree_multi.pyx.tp +3 -3
- multipers/slicer.cp310-win_amd64.pyd +0 -0
- multipers/slicer.pyx +56 -55
- multipers/slicer.pyx.tp +5 -4
- multipers/tbb12.dll +0 -0
- multipers/tbbbind_2_5.dll +0 -0
- multipers/tbbmalloc.dll +0 -0
- multipers/tbbmalloc_proxy.dll +0 -0
- {multipers-2.3.2.dist-info → multipers-2.3.3.dist-info}/METADATA +6 -1
- {multipers-2.3.2.dist-info → multipers-2.3.3.dist-info}/RECORD +35 -35
- {multipers-2.3.2.dist-info → multipers-2.3.3.dist-info}/WHEEL +1 -1
- {multipers-2.3.2.dist-info → multipers-2.3.3.dist-info}/licenses/LICENSE +0 -0
- {multipers-2.3.2.dist-info → multipers-2.3.3.dist-info}/top_level.txt +0 -0
multipers/plots.py
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
|
+
from warnings import warn
|
|
2
3
|
|
|
4
|
+
import matplotlib.colors as mcolors
|
|
3
5
|
import matplotlib.pyplot as plt
|
|
4
6
|
import numpy as np
|
|
7
|
+
from matplotlib.colors import ListedColormap
|
|
8
|
+
from numpy.typing import ArrayLike
|
|
9
|
+
|
|
10
|
+
from multipers.array_api import to_numpy
|
|
11
|
+
|
|
12
|
+
_custom_colors = [
|
|
13
|
+
"#03045e",
|
|
14
|
+
"#0077b6",
|
|
15
|
+
"#00b4d8",
|
|
16
|
+
"#90e0ef",
|
|
17
|
+
]
|
|
18
|
+
_cmap_ = ListedColormap(_custom_colors)
|
|
19
|
+
_cmap = mcolors.LinearSegmentedColormap.from_list(
|
|
20
|
+
"continuous_cmap", _cmap_.colors, N=256
|
|
21
|
+
)
|
|
5
22
|
|
|
6
|
-
try:
|
|
7
|
-
import torch
|
|
8
|
-
istensor = torch.is_tensor
|
|
9
|
-
except ImportError:
|
|
10
|
-
istensor = lambda x: False
|
|
11
23
|
|
|
12
24
|
def _plot_rectangle(rectangle: np.ndarray, weight, **plt_kwargs):
|
|
13
25
|
rectangle = np.asarray(rectangle)
|
|
@@ -69,10 +81,11 @@ def _plot_signed_measure_4(
|
|
|
69
81
|
**plt_kwargs, # ignored ftm
|
|
70
82
|
):
|
|
71
83
|
# compute the maximal rectangle area
|
|
72
|
-
pts = np.clip(pts, a_min=-np.inf,
|
|
84
|
+
pts = np.clip(pts, a_min=-np.inf,
|
|
85
|
+
a_max=np.array((*threshold, *threshold))[None, :])
|
|
73
86
|
alpha_rescaling = 0
|
|
74
87
|
for rectangle, weight in zip(pts, weights):
|
|
75
|
-
if rectangle[2]
|
|
88
|
+
if rectangle[2] >= x_smoothing * rectangle[0]:
|
|
76
89
|
alpha_rescaling = max(
|
|
77
90
|
alpha_rescaling,
|
|
78
91
|
(rectangle[2] / x_smoothing - rectangle[0])
|
|
@@ -81,7 +94,7 @@ def _plot_signed_measure_4(
|
|
|
81
94
|
# draw the rectangles
|
|
82
95
|
for rectangle, weight in zip(pts, weights):
|
|
83
96
|
# draw only the rectangles that have not been reduced to the empty set
|
|
84
|
-
if rectangle[2]
|
|
97
|
+
if rectangle[2] >= x_smoothing * rectangle[0]:
|
|
85
98
|
# make the alpha channel proportional to the rectangle's area
|
|
86
99
|
if area_alpha:
|
|
87
100
|
_plot_rectangle(
|
|
@@ -121,11 +134,8 @@ def plot_signed_measure(signed_measure, threshold=None, ax=None, **plt_kwargs):
|
|
|
121
134
|
else:
|
|
122
135
|
plt.sca(ax)
|
|
123
136
|
pts, weights = signed_measure
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if istensor(weights):
|
|
127
|
-
weights = weights.detach().numpy()
|
|
128
|
-
pts = np.asarray(pts)
|
|
137
|
+
pts = to_numpy(pts)
|
|
138
|
+
weights = to_numpy(weights)
|
|
129
139
|
num_pts = pts.shape[0]
|
|
130
140
|
num_parameters = pts.shape[1]
|
|
131
141
|
if threshold is None:
|
|
@@ -137,16 +147,9 @@ def plot_signed_measure(signed_measure, threshold=None, ax=None, **plt_kwargs):
|
|
|
137
147
|
else:
|
|
138
148
|
pts_ = pts
|
|
139
149
|
threshold = np.max(np.ma.masked_invalid(pts_), axis=0)
|
|
140
|
-
threshold = np.max(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
else:
|
|
144
|
-
import torch
|
|
145
|
-
|
|
146
|
-
if isinstance(pts, torch.Tensor):
|
|
147
|
-
pts = pts.detach().numpy()
|
|
148
|
-
else:
|
|
149
|
-
raise Exception("Invalid measure type.")
|
|
150
|
+
threshold = np.max(
|
|
151
|
+
[threshold, [plt.gca().get_xlim()[1], plt.gca().get_ylim()[1]]], axis=0
|
|
152
|
+
)
|
|
150
153
|
|
|
151
154
|
assert num_parameters in (2, 4)
|
|
152
155
|
if num_parameters == 2:
|
|
@@ -168,7 +171,8 @@ def plot_signed_measures(signed_measures, threshold=None, size=4):
|
|
|
168
171
|
nrows=1, ncols=num_degrees, figsize=(num_degrees * size, size)
|
|
169
172
|
)
|
|
170
173
|
for ax, signed_measure in zip(axes, signed_measures):
|
|
171
|
-
plot_signed_measure(signed_measure=signed_measure,
|
|
174
|
+
plot_signed_measure(signed_measure=signed_measure,
|
|
175
|
+
ax=ax, threshold=threshold)
|
|
172
176
|
plt.tight_layout()
|
|
173
177
|
|
|
174
178
|
|
|
@@ -178,8 +182,9 @@ def plot_surface(
|
|
|
178
182
|
fig=None,
|
|
179
183
|
ax=None,
|
|
180
184
|
cmap: Optional[str] = None,
|
|
181
|
-
discrete_surface=False,
|
|
182
|
-
has_negative_values=False,
|
|
185
|
+
discrete_surface: bool = False,
|
|
186
|
+
has_negative_values: bool = False,
|
|
187
|
+
contour: bool = True,
|
|
183
188
|
**plt_args,
|
|
184
189
|
):
|
|
185
190
|
import matplotlib
|
|
@@ -196,14 +201,18 @@ def plot_surface(
|
|
|
196
201
|
if discrete_surface:
|
|
197
202
|
cmap = matplotlib.colormaps["gray_r"]
|
|
198
203
|
else:
|
|
199
|
-
cmap =
|
|
204
|
+
cmap = _cmap
|
|
205
|
+
if discrete_surface or not contour:
|
|
206
|
+
# for shading="flat"
|
|
207
|
+
grid = [np.concatenate([g, [g[-1]*1.1 - .1*g[0]]]) for g in grid]
|
|
200
208
|
if discrete_surface:
|
|
201
209
|
if has_negative_values:
|
|
202
210
|
bounds = np.arange(-5, 6, 1, dtype=int)
|
|
203
211
|
else:
|
|
204
212
|
bounds = np.arange(0, 11, 1, dtype=int)
|
|
205
213
|
norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N, extend="max")
|
|
206
|
-
im = ax.pcolormesh(grid[0], grid[1], hf.T, cmap=cmap,
|
|
214
|
+
im = ax.pcolormesh(grid[0], grid[1], hf.T, cmap=cmap,
|
|
215
|
+
norm=norm, shading="flat", **plt_args)
|
|
207
216
|
cbar = fig.colorbar(
|
|
208
217
|
matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm),
|
|
209
218
|
spacing="proportional",
|
|
@@ -211,7 +220,14 @@ def plot_surface(
|
|
|
211
220
|
)
|
|
212
221
|
cbar.set_ticks(ticks=bounds, labels=bounds)
|
|
213
222
|
return im
|
|
214
|
-
|
|
223
|
+
|
|
224
|
+
if contour:
|
|
225
|
+
levels = plt_args.pop("levels", 50)
|
|
226
|
+
im = ax.contourf(grid[0], grid[1], hf.T,
|
|
227
|
+
cmap=cmap, levels=levels, **plt_args)
|
|
228
|
+
else:
|
|
229
|
+
im = ax.pcolormesh(grid[0], grid[1], hf.T,
|
|
230
|
+
cmap=cmap, shading="flat", **plt_args)
|
|
215
231
|
return im
|
|
216
232
|
|
|
217
233
|
|
|
@@ -255,7 +271,7 @@ def plot2d_PyModule(
|
|
|
255
271
|
dimension=-1,
|
|
256
272
|
separated=False,
|
|
257
273
|
min_persistence=0,
|
|
258
|
-
alpha
|
|
274
|
+
alpha=None,
|
|
259
275
|
verbose=False,
|
|
260
276
|
save=False,
|
|
261
277
|
dpi=200,
|
|
@@ -273,12 +289,14 @@ def plot2d_PyModule(
|
|
|
273
289
|
|
|
274
290
|
shapely = True and shapely
|
|
275
291
|
except ImportError:
|
|
276
|
-
from warnings import warn
|
|
277
|
-
|
|
278
292
|
shapely = False
|
|
279
293
|
warn(
|
|
280
294
|
"Shapely not installed. Fallbacking to matplotlib. The plots may be inacurate."
|
|
281
295
|
)
|
|
296
|
+
if alpha is None:
|
|
297
|
+
alpha = 0.8 if shapely else 1
|
|
298
|
+
if not shapely and alpha != 1:
|
|
299
|
+
warn("Opacity without shapely will lead to incorect plots.")
|
|
282
300
|
cmap = (
|
|
283
301
|
matplotlib.colormaps["Spectral"] if cmap is None else matplotlib.colormaps[cmap]
|
|
284
302
|
)
|
|
@@ -304,25 +322,30 @@ def plot2d_PyModule(
|
|
|
304
322
|
trivial_summand = False
|
|
305
323
|
if shapely:
|
|
306
324
|
list_of_rect.append(
|
|
307
|
-
_rectangle_box(
|
|
325
|
+
_rectangle_box(
|
|
326
|
+
birth[0], birth[1], death[0], death[1])
|
|
308
327
|
)
|
|
309
328
|
else:
|
|
310
329
|
list_of_rect.append(
|
|
311
|
-
_rectangle(birth, death, cmap(
|
|
330
|
+
_rectangle(birth, death, cmap(
|
|
331
|
+
i / n_summands), alpha)
|
|
312
332
|
)
|
|
313
333
|
if not (trivial_summand):
|
|
314
334
|
if separated:
|
|
315
335
|
fig, ax = plt.subplots()
|
|
316
|
-
ax.set(xlim=[box[0][0], box[1][0]],
|
|
336
|
+
ax.set(xlim=[box[0][0], box[1][0]],
|
|
337
|
+
ylim=[box[0][1], box[1][1]])
|
|
317
338
|
if shapely:
|
|
318
339
|
summand_shape = union_all(list_of_rect)
|
|
319
340
|
if type(summand_shape) is _Polygon:
|
|
320
341
|
xs, ys = summand_shape.exterior.xy
|
|
321
|
-
ax.fill(xs, ys, alpha=alpha, fc=cmap(
|
|
342
|
+
ax.fill(xs, ys, alpha=alpha, fc=cmap(
|
|
343
|
+
i / n_summands), ec="None")
|
|
322
344
|
else:
|
|
323
345
|
for polygon in summand_shape.geoms:
|
|
324
346
|
xs, ys = polygon.exterior.xy
|
|
325
|
-
ax.fill(xs, ys, alpha=alpha, fc=cmap(
|
|
347
|
+
ax.fill(xs, ys, alpha=alpha, fc=cmap(
|
|
348
|
+
i / n_summands), ec="None")
|
|
326
349
|
else:
|
|
327
350
|
for rectangle in list_of_rect:
|
|
328
351
|
ax.add_patch(rectangle)
|
|
@@ -341,3 +364,107 @@ def plot2d_PyModule(
|
|
|
341
364
|
if dimension >= 0:
|
|
342
365
|
plt.title(rf"$H_{dimension}$ $2$-persistence")
|
|
343
366
|
return
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def plot_simplicial_complex(
|
|
370
|
+
st, pts: ArrayLike, x: float, y: float, mma=None, degree=None
|
|
371
|
+
):
|
|
372
|
+
"""
|
|
373
|
+
Scatters the points, with the simplices in the filtration at coordinates (x,y).
|
|
374
|
+
if an mma module is given, plots it in a second axis
|
|
375
|
+
"""
|
|
376
|
+
if mma is not None:
|
|
377
|
+
fig, (a, b) = plt.subplots(ncols=2, figsize=(15, 5))
|
|
378
|
+
plt.sca(a)
|
|
379
|
+
plot_simplicial_complex(st, pts, x, y)
|
|
380
|
+
plt.sca(b)
|
|
381
|
+
mma.plot(degree=degree)
|
|
382
|
+
box = mma.get_box()
|
|
383
|
+
a, b, c, d = box.ravel()
|
|
384
|
+
mma.plot(degree=1, min_persistence=0.01)
|
|
385
|
+
plt.vlines(x, b, d, color="k", linestyle="--")
|
|
386
|
+
plt.hlines(y, a, c, color="k", linestyle="--")
|
|
387
|
+
plt.scatter([x], [y], c="r", zorder=10)
|
|
388
|
+
plt.text(x + 0.01 * (b - a), y + 0.01 * (d - c), f"({x},{y})")
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
pts = np.asarray(pts)
|
|
392
|
+
values = np.array([-f[1] for s, f in st.get_skeleton(0)])
|
|
393
|
+
qs = np.quantile(values, np.linspace(0, 1, 100))
|
|
394
|
+
|
|
395
|
+
def color_idx(d):
|
|
396
|
+
return np.searchsorted(qs, d) / 100
|
|
397
|
+
|
|
398
|
+
from matplotlib.pyplot import get_cmap
|
|
399
|
+
|
|
400
|
+
def color(d):
|
|
401
|
+
return get_cmap("viridis")([0, color_idx(d), 1])[1]
|
|
402
|
+
|
|
403
|
+
cols_pc = np.asarray([color(v) for v in values])
|
|
404
|
+
ax = plt.gca()
|
|
405
|
+
for s, f in st: # simplexe, filtration
|
|
406
|
+
density = -f[1]
|
|
407
|
+
if len(s) <= 1 or f[0] > x or density < -y: # simplexe = point
|
|
408
|
+
continue
|
|
409
|
+
if len(s) == 2: # simplexe = segment
|
|
410
|
+
xx = np.array([pts[a, 0] for a in s])
|
|
411
|
+
yy = np.array([pts[a, 1] for a in s])
|
|
412
|
+
plt.plot(xx, yy, c=color(density), alpha=1,
|
|
413
|
+
zorder=10 * density, lw=1.5)
|
|
414
|
+
if len(s) == 3: # simplexe = triangle
|
|
415
|
+
xx = np.array([pts[a, 0] for a in s])
|
|
416
|
+
yy = np.array([pts[a, 1] for a in s])
|
|
417
|
+
_c = color(density)
|
|
418
|
+
ax.fill(xx, yy, c=_c, alpha=0.3, zorder=0)
|
|
419
|
+
out = plt.scatter(pts[:, 0], pts[:, 1], c=cols_pc, zorder=10, s=10)
|
|
420
|
+
ax.set_aspect(1)
|
|
421
|
+
return out
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def plot_point_cloud(
|
|
425
|
+
pts,
|
|
426
|
+
function,
|
|
427
|
+
x,
|
|
428
|
+
y,
|
|
429
|
+
mma=None,
|
|
430
|
+
degree=None,
|
|
431
|
+
ball_alpha=0.3,
|
|
432
|
+
point_cmap="viridis",
|
|
433
|
+
color_bias=1,
|
|
434
|
+
ball_color=None,
|
|
435
|
+
point_size=20,
|
|
436
|
+
):
|
|
437
|
+
if mma is not None:
|
|
438
|
+
fig, (a, b) = plt.subplots(ncols=2, figsize=(15, 5))
|
|
439
|
+
plt.sca(a)
|
|
440
|
+
plot_point_cloud(pts, function, x, y)
|
|
441
|
+
plt.sca(b)
|
|
442
|
+
mma.plot(degree=degree)
|
|
443
|
+
box = mma.get_box()
|
|
444
|
+
a, b, c, d = box.ravel()
|
|
445
|
+
mma.plot(degree=1, min_persistence=0.01)
|
|
446
|
+
plt.vlines(x, b, d, color="k", linestyle="--")
|
|
447
|
+
plt.hlines(y, a, c, color="k", linestyle="--")
|
|
448
|
+
plt.scatter([x], [y], c="r", zorder=10)
|
|
449
|
+
plt.text(x + 0.01 * (b - a), y + 0.01 * (d - c), f"({x},{y})")
|
|
450
|
+
return
|
|
451
|
+
values = -function
|
|
452
|
+
qs = np.quantile(values, np.linspace(0, 1, 100))
|
|
453
|
+
|
|
454
|
+
def color_idx(d):
|
|
455
|
+
return np.searchsorted(qs, d * color_bias) / 100
|
|
456
|
+
|
|
457
|
+
from matplotlib.collections import PatchCollection
|
|
458
|
+
from matplotlib.pyplot import get_cmap
|
|
459
|
+
|
|
460
|
+
def color(d):
|
|
461
|
+
return get_cmap(point_cmap)([0, color_idx(d), 1])[1]
|
|
462
|
+
|
|
463
|
+
_colors = np.array([color(v) for v in values])
|
|
464
|
+
ax = plt.gca()
|
|
465
|
+
idx = function <= y
|
|
466
|
+
circles = [plt.Circle(pt, x) for pt, c in zip(pts[idx], function)]
|
|
467
|
+
pc = PatchCollection(circles, alpha=ball_alpha, color=ball_color)
|
|
468
|
+
ax.add_collection(pc)
|
|
469
|
+
plt.scatter(*pts.T, c=_colors, s=point_size)
|
|
470
|
+
ax.set_aspect(1)
|
|
Binary file
|
multipers/point_measure.pyx
CHANGED
|
@@ -11,6 +11,7 @@ from collections import defaultdict
|
|
|
11
11
|
cnp.import_array()
|
|
12
12
|
from scipy import sparse
|
|
13
13
|
|
|
14
|
+
from multipers.array_api import api_from_tensor
|
|
14
15
|
|
|
15
16
|
import multipers.grids as mpg
|
|
16
17
|
|
|
@@ -31,7 +32,6 @@ import cython
|
|
|
31
32
|
cimport cython
|
|
32
33
|
|
|
33
34
|
|
|
34
|
-
|
|
35
35
|
# from scipy.sparse import coo_array
|
|
36
36
|
# from scipy.ndimage import convolve1d
|
|
37
37
|
|
|
@@ -169,7 +169,7 @@ def sparsify(x):
|
|
|
169
169
|
|
|
170
170
|
@cython.boundscheck(False)
|
|
171
171
|
@cython.wraparound(False)
|
|
172
|
-
def
|
|
172
|
+
def clean_signed_measure_old(some_float[:,:] pts, some_int[:] weights, dtype = np.float32):
|
|
173
173
|
"""
|
|
174
174
|
Sum the diracs at the same locations. i.e.,
|
|
175
175
|
returns the minimal sized measure to represent the input.
|
|
@@ -190,6 +190,14 @@ def clean_signed_measure(some_float[:,:] pts, some_int[:] weights, dtype = np.fl
|
|
|
190
190
|
new_weights = new_weights[idx]
|
|
191
191
|
return (new_pts, new_weights)
|
|
192
192
|
|
|
193
|
+
def clean_signed_measure(pts, w, dtype=np.int32):
|
|
194
|
+
api = api_from_tensor(pts)
|
|
195
|
+
_, idx, inv = np.unique(api.asnumpy(pts), return_index=True, return_inverse=True, axis=0)
|
|
196
|
+
new_w = np.bincount(inv, weights=w).astype(w.dtype)
|
|
197
|
+
pts, w = pts[idx], new_w
|
|
198
|
+
idx = w!=0
|
|
199
|
+
return pts[idx],w[idx]
|
|
200
|
+
|
|
193
201
|
def clean_sms(sms):
|
|
194
202
|
"""
|
|
195
203
|
Sum the diracs at the same locations. i.e.,
|
|
@@ -324,3 +332,64 @@ def estimate_rank_from_rank_sm(sm:tuple, a, b)->np.int64:
|
|
|
324
332
|
return w[idx].sum()
|
|
325
333
|
|
|
326
334
|
|
|
335
|
+
def rectangle_to_hook_minimal_signed_barcode(pts,w,):
|
|
336
|
+
if pts.shape[1] != 4:
|
|
337
|
+
raise NotImplementedError(
|
|
338
|
+
"Only works for 2-parameter persistence modules for the moment."
|
|
339
|
+
)
|
|
340
|
+
api = api_from_tensor(pts)
|
|
341
|
+
pts = api.astensor(pts)
|
|
342
|
+
w = np.asarray(w)
|
|
343
|
+
## [a,b], [a, a0b1], [a,b0a1], proj, V,H
|
|
344
|
+
|
|
345
|
+
projectives_idx = (pts[:,3] == np.inf) * (pts[:,2] == np.inf)
|
|
346
|
+
pts_proj = pts[projectives_idx]
|
|
347
|
+
w_proj = w[projectives_idx]
|
|
348
|
+
pts = pts[~projectives_idx]
|
|
349
|
+
w = w[~projectives_idx]
|
|
350
|
+
# print("projectives:", pts_proj)
|
|
351
|
+
|
|
352
|
+
vert_blocks_idx = pts[:,3] == np.inf
|
|
353
|
+
pts_V = pts[vert_blocks_idx]
|
|
354
|
+
w_V = w[vert_blocks_idx]
|
|
355
|
+
pts_V[:,3] = pts_V[:,1]
|
|
356
|
+
pts = pts[~vert_blocks_idx]
|
|
357
|
+
w = w[~vert_blocks_idx]
|
|
358
|
+
# print("vertical:", pts_V)
|
|
359
|
+
|
|
360
|
+
h_idx = pts[:,2] == np.inf
|
|
361
|
+
pts_H = pts[h_idx]
|
|
362
|
+
w_H = w[h_idx]
|
|
363
|
+
pts_H[:,2] = pts_H[:,0]
|
|
364
|
+
pts = pts[~h_idx]
|
|
365
|
+
w = w[~h_idx]
|
|
366
|
+
# print("horizontal:", pts_H)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
new_w = api.cat([-w, w, w, w_proj,w_V,w_H])
|
|
370
|
+
|
|
371
|
+
pts_b0a1 = api.tensor(pts)
|
|
372
|
+
pts_b0a1[:,3] = pts[:,1]
|
|
373
|
+
pts_a0b1 = api.tensor(pts)
|
|
374
|
+
pts_a0b1[:,2] = pts[:,0]
|
|
375
|
+
|
|
376
|
+
new_pts = api.cat([
|
|
377
|
+
pts,
|
|
378
|
+
pts_b0a1,
|
|
379
|
+
pts_a0b1,
|
|
380
|
+
pts_proj,
|
|
381
|
+
pts_V,
|
|
382
|
+
pts_H
|
|
383
|
+
], axis=0)
|
|
384
|
+
# pts,w = new_pts,new_w
|
|
385
|
+
pts,w = clean_signed_measure(new_pts,new_w)
|
|
386
|
+
|
|
387
|
+
# Everything infinite is handled separately anyway
|
|
388
|
+
# inf0 = pts[:,2] == np.inf
|
|
389
|
+
# inf1 = pts[:,3] == np.inf
|
|
390
|
+
# pts[inf0,3] = pts[inf0,1]
|
|
391
|
+
# pts[inf1,2] = pts[inf1,0]
|
|
392
|
+
# pts,w = clean_signed_measure(pts,w)
|
|
393
|
+
|
|
394
|
+
return pts,w
|
|
395
|
+
|
|
Binary file
|
multipers/simplex_tree_multi.pxd
CHANGED
|
@@ -117,8 +117,8 @@ cdef extern from "Simplex_tree_multi_interface.h" namespace "Gudhi::multiparamet
|
|
|
117
117
|
void to_std(intptr_t, Line[double],int ) nogil
|
|
118
118
|
void to_std_linear_projection(intptr_t, vector[double]) nogil
|
|
119
119
|
void squeeze_filtration_inplace(vector[vector[double]] &, bool) nogil
|
|
120
|
-
void squeeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
121
|
-
void unsqueeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
120
|
+
void squeeze_filtration(intptr_t, vector[vector[double]] &) except + nogil
|
|
121
|
+
void unsqueeze_filtration(intptr_t, vector[vector[double]] &) except + nogil
|
|
122
122
|
vector[vector[vector[value_type]]] get_filtration_values(const vector[int]&) nogil
|
|
123
123
|
|
|
124
124
|
|