multipers 2.3.0__cp312-cp312-win_amd64.whl → 2.3.2__cp312-cp312-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 +71 -65
- multipers/array_api/__init__.py +39 -0
- multipers/array_api/numpy.py +34 -0
- multipers/array_api/torch.py +35 -0
- multipers/distances.py +6 -2
- multipers/{ml/convolutions.py → filtrations/density.py} +67 -13
- multipers/filtrations/filtrations.py +76 -17
- multipers/function_rips.cp312-win_amd64.pyd +0 -0
- multipers/grids.cp312-win_amd64.pyd +0 -0
- multipers/grids.pyx +144 -61
- multipers/gudhi/Simplex_tree_multi_interface.h +36 -1
- multipers/gudhi/gudhi/Multi_persistence/Box.h +3 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +18 -9
- multipers/gudhi/mma_interface_h0.h +1 -1
- multipers/gudhi/mma_interface_matrix.h +10 -1
- multipers/gudhi/naive_merge_tree.h +1 -1
- multipers/gudhi/truc.h +555 -42
- multipers/io.cp312-win_amd64.pyd +0 -0
- multipers/io.pyx +26 -93
- multipers/ml/mma.py +4 -4
- multipers/ml/point_clouds.py +2 -2
- multipers/ml/signed_measures.py +63 -65
- multipers/mma_structures.cp312-win_amd64.pyd +0 -0
- multipers/mma_structures.pxd +2 -1
- multipers/mma_structures.pyx +56 -16
- multipers/mma_structures.pyx.tp +14 -5
- multipers/multiparameter_module_approximation/approximation.h +48 -14
- multipers/multiparameter_module_approximation.cp312-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +27 -8
- multipers/plots.py +2 -1
- multipers/point_measure.cp312-win_amd64.pyd +0 -0
- multipers/point_measure.pyx +6 -2
- multipers/simplex_tree_multi.cp312-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.pxd +1 -0
- multipers/simplex_tree_multi.pyx +632 -146
- multipers/simplex_tree_multi.pyx.tp +92 -24
- multipers/slicer.cp312-win_amd64.pyd +0 -0
- multipers/slicer.pxd +779 -177
- multipers/slicer.pxd.tp +24 -5
- multipers/slicer.pyx +5657 -1427
- multipers/slicer.pyx.tp +211 -48
- multipers/tbb12.dll +0 -0
- multipers/tbbbind_2_5.dll +0 -0
- multipers/tbbmalloc.dll +0 -0
- multipers/tbbmalloc_proxy.dll +0 -0
- multipers/tensor/tensor.h +1 -1
- multipers/tests/__init__.py +9 -4
- multipers/torch/diff_grids.py +30 -7
- multipers/torch/rips_density.py +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.2.dist-info}/METADATA +4 -25
- {multipers-2.3.0.dist-info → multipers-2.3.2.dist-info}/RECORD +54 -51
- {multipers-2.3.0.dist-info → multipers-2.3.2.dist-info}/WHEEL +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.2.dist-info/licenses}/LICENSE +0 -0
- {multipers-2.3.0.dist-info → multipers-2.3.2.dist-info}/top_level.txt +0 -0
multipers/mma_structures.pyx
CHANGED
|
@@ -97,6 +97,11 @@ cdef class PySummand_f64:
|
|
|
97
97
|
return v[0].num_parameters()
|
|
98
98
|
v = self.sum.get_death_list()
|
|
99
99
|
return v[0].num_parameters()
|
|
100
|
+
def __eq__(self, PySummand_f64 other):
|
|
101
|
+
return self.sum == other.sum
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
100
105
|
|
|
101
106
|
cdef inline get_summand_filtration_values_f64(Summand[double] summand):
|
|
102
107
|
r"""
|
|
@@ -161,6 +166,10 @@ cdef class PyModule_f64:
|
|
|
161
166
|
|
|
162
167
|
cdef set(self, Module[double] m):
|
|
163
168
|
self.cmod = m
|
|
169
|
+
|
|
170
|
+
def __eq__(self, PyModule_f64 other):
|
|
171
|
+
return self.cmod == other.cmod
|
|
172
|
+
|
|
164
173
|
def merge(self, PyModule_f64 other, int dim=-1):
|
|
165
174
|
r"""
|
|
166
175
|
Merges two modules into one
|
|
@@ -176,7 +185,9 @@ cdef class PyModule_f64:
|
|
|
176
185
|
Copy module from a memory pointer. Unsafe.
|
|
177
186
|
"""
|
|
178
187
|
self.cmod = move(dereference(<Module[double]*>(module_ptr)))
|
|
179
|
-
def set_box(self,
|
|
188
|
+
def set_box(self, box):
|
|
189
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
190
|
+
pybox = PyBox_f64(box[0], box[1])
|
|
180
191
|
cdef Box[double] cbox = pybox.box
|
|
181
192
|
with nogil:
|
|
182
193
|
self.cmod.set_box(cbox)
|
|
@@ -580,7 +591,6 @@ cdef class PyModule_f64:
|
|
|
580
591
|
cdef Box[double] c_box = Box[double](box)
|
|
581
592
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
582
593
|
if plot:
|
|
583
|
-
plt.figure()
|
|
584
594
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
585
595
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
586
596
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -614,7 +624,6 @@ cdef class PyModule_f64:
|
|
|
614
624
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[double](box), resolution))
|
|
615
625
|
if plot:
|
|
616
626
|
to_plot = np.sum(out, axis=0)
|
|
617
|
-
plt.figure()
|
|
618
627
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
619
628
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
620
629
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -961,8 +970,8 @@ cdef dump_summand_f64(Summand[double]& summand):
|
|
|
961
970
|
cdef vector[One_critical_filtration[double]] births = summand.get_birth_list()
|
|
962
971
|
cdef vector[One_critical_filtration[double]] deaths = summand.get_death_list()
|
|
963
972
|
return (
|
|
964
|
-
_vff21cview_f64(births
|
|
965
|
-
_vff21cview_f64(deaths
|
|
973
|
+
np.array(_vff21cview_f64(births)),
|
|
974
|
+
np.array(_vff21cview_f64(deaths)),
|
|
966
975
|
summand.get_dimension(),
|
|
967
976
|
)
|
|
968
977
|
|
|
@@ -1049,6 +1058,11 @@ cdef class PySummand_f32:
|
|
|
1049
1058
|
return v[0].num_parameters()
|
|
1050
1059
|
v = self.sum.get_death_list()
|
|
1051
1060
|
return v[0].num_parameters()
|
|
1061
|
+
def __eq__(self, PySummand_f32 other):
|
|
1062
|
+
return self.sum == other.sum
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1052
1066
|
|
|
1053
1067
|
cdef inline get_summand_filtration_values_f32(Summand[float] summand):
|
|
1054
1068
|
r"""
|
|
@@ -1113,6 +1127,10 @@ cdef class PyModule_f32:
|
|
|
1113
1127
|
|
|
1114
1128
|
cdef set(self, Module[float] m):
|
|
1115
1129
|
self.cmod = m
|
|
1130
|
+
|
|
1131
|
+
def __eq__(self, PyModule_f32 other):
|
|
1132
|
+
return self.cmod == other.cmod
|
|
1133
|
+
|
|
1116
1134
|
def merge(self, PyModule_f32 other, int dim=-1):
|
|
1117
1135
|
r"""
|
|
1118
1136
|
Merges two modules into one
|
|
@@ -1128,7 +1146,9 @@ cdef class PyModule_f32:
|
|
|
1128
1146
|
Copy module from a memory pointer. Unsafe.
|
|
1129
1147
|
"""
|
|
1130
1148
|
self.cmod = move(dereference(<Module[float]*>(module_ptr)))
|
|
1131
|
-
def set_box(self,
|
|
1149
|
+
def set_box(self, box):
|
|
1150
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
1151
|
+
pybox = PyBox_f32(box[0], box[1])
|
|
1132
1152
|
cdef Box[float] cbox = pybox.box
|
|
1133
1153
|
with nogil:
|
|
1134
1154
|
self.cmod.set_box(cbox)
|
|
@@ -1532,7 +1552,6 @@ cdef class PyModule_f32:
|
|
|
1532
1552
|
cdef Box[float] c_box = Box[float](box)
|
|
1533
1553
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
1534
1554
|
if plot:
|
|
1535
|
-
plt.figure()
|
|
1536
1555
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
1537
1556
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
1538
1557
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -1566,7 +1585,6 @@ cdef class PyModule_f32:
|
|
|
1566
1585
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[float](box), resolution))
|
|
1567
1586
|
if plot:
|
|
1568
1587
|
to_plot = np.sum(out, axis=0)
|
|
1569
|
-
plt.figure()
|
|
1570
1588
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
1571
1589
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
1572
1590
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -1913,8 +1931,8 @@ cdef dump_summand_f32(Summand[float]& summand):
|
|
|
1913
1931
|
cdef vector[One_critical_filtration[float]] births = summand.get_birth_list()
|
|
1914
1932
|
cdef vector[One_critical_filtration[float]] deaths = summand.get_death_list()
|
|
1915
1933
|
return (
|
|
1916
|
-
_vff21cview_f32(births
|
|
1917
|
-
_vff21cview_f32(deaths
|
|
1934
|
+
np.array(_vff21cview_f32(births)),
|
|
1935
|
+
np.array(_vff21cview_f32(deaths)),
|
|
1918
1936
|
summand.get_dimension(),
|
|
1919
1937
|
)
|
|
1920
1938
|
|
|
@@ -2001,6 +2019,11 @@ cdef class PySummand_i32:
|
|
|
2001
2019
|
return v[0].num_parameters()
|
|
2002
2020
|
v = self.sum.get_death_list()
|
|
2003
2021
|
return v[0].num_parameters()
|
|
2022
|
+
def __eq__(self, PySummand_i32 other):
|
|
2023
|
+
return self.sum == other.sum
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
|
|
2004
2027
|
|
|
2005
2028
|
cdef inline get_summand_filtration_values_i32(Summand[int32_t] summand):
|
|
2006
2029
|
r"""
|
|
@@ -2065,6 +2088,10 @@ cdef class PyModule_i32:
|
|
|
2065
2088
|
|
|
2066
2089
|
cdef set(self, Module[int32_t] m):
|
|
2067
2090
|
self.cmod = m
|
|
2091
|
+
|
|
2092
|
+
def __eq__(self, PyModule_i32 other):
|
|
2093
|
+
return self.cmod == other.cmod
|
|
2094
|
+
|
|
2068
2095
|
def merge(self, PyModule_i32 other, int dim=-1):
|
|
2069
2096
|
r"""
|
|
2070
2097
|
Merges two modules into one
|
|
@@ -2080,7 +2107,9 @@ cdef class PyModule_i32:
|
|
|
2080
2107
|
Copy module from a memory pointer. Unsafe.
|
|
2081
2108
|
"""
|
|
2082
2109
|
self.cmod = move(dereference(<Module[int32_t]*>(module_ptr)))
|
|
2083
|
-
def set_box(self,
|
|
2110
|
+
def set_box(self, box):
|
|
2111
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
2112
|
+
pybox = PyBox_i32(box[0], box[1])
|
|
2084
2113
|
cdef Box[int32_t] cbox = pybox.box
|
|
2085
2114
|
with nogil:
|
|
2086
2115
|
self.cmod.set_box(cbox)
|
|
@@ -2281,8 +2310,8 @@ cdef dump_summand_i32(Summand[int32_t]& summand):
|
|
|
2281
2310
|
cdef vector[One_critical_filtration[int32_t]] births = summand.get_birth_list()
|
|
2282
2311
|
cdef vector[One_critical_filtration[int32_t]] deaths = summand.get_death_list()
|
|
2283
2312
|
return (
|
|
2284
|
-
_vff21cview_i32(births
|
|
2285
|
-
_vff21cview_i32(deaths
|
|
2313
|
+
np.array(_vff21cview_i32(births)),
|
|
2314
|
+
np.array(_vff21cview_i32(deaths)),
|
|
2286
2315
|
summand.get_dimension(),
|
|
2287
2316
|
)
|
|
2288
2317
|
|
|
@@ -2369,6 +2398,11 @@ cdef class PySummand_i64:
|
|
|
2369
2398
|
return v[0].num_parameters()
|
|
2370
2399
|
v = self.sum.get_death_list()
|
|
2371
2400
|
return v[0].num_parameters()
|
|
2401
|
+
def __eq__(self, PySummand_i64 other):
|
|
2402
|
+
return self.sum == other.sum
|
|
2403
|
+
|
|
2404
|
+
|
|
2405
|
+
|
|
2372
2406
|
|
|
2373
2407
|
cdef inline get_summand_filtration_values_i64(Summand[int64_t] summand):
|
|
2374
2408
|
r"""
|
|
@@ -2433,6 +2467,10 @@ cdef class PyModule_i64:
|
|
|
2433
2467
|
|
|
2434
2468
|
cdef set(self, Module[int64_t] m):
|
|
2435
2469
|
self.cmod = m
|
|
2470
|
+
|
|
2471
|
+
def __eq__(self, PyModule_i64 other):
|
|
2472
|
+
return self.cmod == other.cmod
|
|
2473
|
+
|
|
2436
2474
|
def merge(self, PyModule_i64 other, int dim=-1):
|
|
2437
2475
|
r"""
|
|
2438
2476
|
Merges two modules into one
|
|
@@ -2448,7 +2486,9 @@ cdef class PyModule_i64:
|
|
|
2448
2486
|
Copy module from a memory pointer. Unsafe.
|
|
2449
2487
|
"""
|
|
2450
2488
|
self.cmod = move(dereference(<Module[int64_t]*>(module_ptr)))
|
|
2451
|
-
def set_box(self,
|
|
2489
|
+
def set_box(self, box):
|
|
2490
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
2491
|
+
pybox = PyBox_i64(box[0], box[1])
|
|
2452
2492
|
cdef Box[int64_t] cbox = pybox.box
|
|
2453
2493
|
with nogil:
|
|
2454
2494
|
self.cmod.set_box(cbox)
|
|
@@ -2649,8 +2689,8 @@ cdef dump_summand_i64(Summand[int64_t]& summand):
|
|
|
2649
2689
|
cdef vector[One_critical_filtration[int64_t]] births = summand.get_birth_list()
|
|
2650
2690
|
cdef vector[One_critical_filtration[int64_t]] deaths = summand.get_death_list()
|
|
2651
2691
|
return (
|
|
2652
|
-
_vff21cview_i64(births
|
|
2653
|
-
_vff21cview_i64(deaths
|
|
2692
|
+
np.array(_vff21cview_i64(births)),
|
|
2693
|
+
np.array(_vff21cview_i64(deaths)),
|
|
2654
2694
|
summand.get_dimension(),
|
|
2655
2695
|
)
|
|
2656
2696
|
|
multipers/mma_structures.pyx.tp
CHANGED
|
@@ -118,6 +118,11 @@ cdef class PySummand_{{SHORT}}:
|
|
|
118
118
|
return v[0].num_parameters()
|
|
119
119
|
v = self.sum.get_death_list()
|
|
120
120
|
return v[0].num_parameters()
|
|
121
|
+
def __eq__(self, PySummand_{{SHORT}} other):
|
|
122
|
+
return self.sum == other.sum
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
121
126
|
|
|
122
127
|
cdef inline get_summand_filtration_values_{{SHORT}}(Summand[{{CTYPE}}] summand):
|
|
123
128
|
r"""
|
|
@@ -182,6 +187,10 @@ cdef class PyModule_{{SHORT}}:
|
|
|
182
187
|
|
|
183
188
|
cdef set(self, Module[{{CTYPE}}] m):
|
|
184
189
|
self.cmod = m
|
|
190
|
+
|
|
191
|
+
def __eq__(self, PyModule_{{SHORT}} other):
|
|
192
|
+
return self.cmod == other.cmod
|
|
193
|
+
|
|
185
194
|
def merge(self, PyModule_{{SHORT}} other, int dim=-1):
|
|
186
195
|
r"""
|
|
187
196
|
Merges two modules into one
|
|
@@ -197,7 +206,9 @@ cdef class PyModule_{{SHORT}}:
|
|
|
197
206
|
Copy module from a memory pointer. Unsafe.
|
|
198
207
|
"""
|
|
199
208
|
self.cmod = move(dereference(<Module[{{CTYPE}}]*>(module_ptr)))
|
|
200
|
-
def set_box(self,
|
|
209
|
+
def set_box(self, box):
|
|
210
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
211
|
+
pybox = PyBox_{{SHORT}}(box[0], box[1])
|
|
201
212
|
cdef Box[{{CTYPE}}] cbox = pybox.box
|
|
202
213
|
with nogil:
|
|
203
214
|
self.cmod.set_box(cbox)
|
|
@@ -602,7 +613,6 @@ cdef class PyModule_{{SHORT}}:
|
|
|
602
613
|
cdef Box[{{CTYPE}}] c_box = Box[{{CTYPE}}](box)
|
|
603
614
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
604
615
|
if plot:
|
|
605
|
-
plt.figure()
|
|
606
616
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
607
617
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
608
618
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -636,7 +646,6 @@ cdef class PyModule_{{SHORT}}:
|
|
|
636
646
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[{{CTYPE}}](box), resolution))
|
|
637
647
|
if plot:
|
|
638
648
|
to_plot = np.sum(out, axis=0)
|
|
639
|
-
plt.figure()
|
|
640
649
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
641
650
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
642
651
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -984,8 +993,8 @@ cdef dump_summand_{{SHORT}}(Summand[{{CTYPE}}]& summand):
|
|
|
984
993
|
cdef vector[One_critical_filtration[{{CTYPE}}]] births = summand.get_birth_list()
|
|
985
994
|
cdef vector[One_critical_filtration[{{CTYPE}}]] deaths = summand.get_death_list()
|
|
986
995
|
return (
|
|
987
|
-
_vff21cview_{{SHORT}}(births
|
|
988
|
-
_vff21cview_{{SHORT}}(deaths
|
|
996
|
+
np.array(_vff21cview_{{SHORT}}(births)),
|
|
997
|
+
np.array(_vff21cview_{{SHORT}}(deaths)),
|
|
989
998
|
summand.get_dimension(),
|
|
990
999
|
)
|
|
991
1000
|
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
#include <limits>
|
|
29
29
|
#include <oneapi/tbb/parallel_for.h>
|
|
30
30
|
#include <string>
|
|
31
|
+
#include <type_traits>
|
|
31
32
|
#include <utility>
|
|
32
33
|
#include <vector>
|
|
33
34
|
|
|
@@ -88,6 +89,8 @@ class Module {
|
|
|
88
89
|
const bool threshold);
|
|
89
90
|
typename module_type::iterator begin();
|
|
90
91
|
typename module_type::iterator end();
|
|
92
|
+
typename module_type::const_iterator begin() const;
|
|
93
|
+
typename module_type::const_iterator end() const;
|
|
91
94
|
|
|
92
95
|
void clean();
|
|
93
96
|
void fill(const value_type precision);
|
|
@@ -192,6 +195,16 @@ class Module {
|
|
|
192
195
|
|
|
193
196
|
std::vector<int> inline get_degree_splits() const;
|
|
194
197
|
|
|
198
|
+
inline friend bool operator==(const Module &a, const Module &b) {
|
|
199
|
+
if (a.get_dimension() != b.get_dimension()) return false;
|
|
200
|
+
if (a.box_ != b.box_) return false;
|
|
201
|
+
if (a.size() != b.size()) return false;
|
|
202
|
+
for (auto i : std::views::iota(0u, a.size())) {
|
|
203
|
+
if (a[i] != b[i]) return false;
|
|
204
|
+
}
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
195
208
|
private:
|
|
196
209
|
module_type module_;
|
|
197
210
|
Box<value_type> box_;
|
|
@@ -281,6 +294,10 @@ class Summand {
|
|
|
281
294
|
// std::swap(sum1.updateDistance_, sum2.updateDistance_);
|
|
282
295
|
};
|
|
283
296
|
|
|
297
|
+
friend bool operator==(const Summand &a, const Summand &b) {
|
|
298
|
+
return a.dimension_ == b.dimension_ && a.birth_corners_ == b.birth_corners_ && a.death_corners_ == b.death_corners_;
|
|
299
|
+
}
|
|
300
|
+
|
|
284
301
|
bool contains(const filtration_type &x) const;
|
|
285
302
|
|
|
286
303
|
inline Box<value_type> get_bounds() const {
|
|
@@ -812,11 +829,21 @@ inline typename Module<value_type>::module_type::iterator Module<value_type>::be
|
|
|
812
829
|
return module_.begin();
|
|
813
830
|
}
|
|
814
831
|
|
|
832
|
+
template <typename value_type>
|
|
833
|
+
inline typename Module<value_type>::module_type::const_iterator Module<value_type>::begin() const {
|
|
834
|
+
return module_.cbegin();
|
|
835
|
+
}
|
|
836
|
+
|
|
815
837
|
template <typename value_type>
|
|
816
838
|
inline typename Module<value_type>::module_type::iterator Module<value_type>::end() {
|
|
817
839
|
return module_.end();
|
|
818
840
|
}
|
|
819
841
|
|
|
842
|
+
template <typename value_type>
|
|
843
|
+
inline typename Module<value_type>::module_type::const_iterator Module<value_type>::end() const {
|
|
844
|
+
return module_.cend();
|
|
845
|
+
}
|
|
846
|
+
|
|
820
847
|
template <typename value_type>
|
|
821
848
|
inline void Module<value_type>::add_summand(Summand<value_type> summand, int degree) {
|
|
822
849
|
if (degree >= 0) summand.set_dimension(degree);
|
|
@@ -2046,14 +2073,16 @@ const Gudhi::multi_filtration::Multi_critical_filtration<value_type> &Summand<va
|
|
|
2046
2073
|
|
|
2047
2074
|
template <typename value_type>
|
|
2048
2075
|
inline void Summand<value_type>::clean() {
|
|
2049
|
-
// birth_corners_.erase(
|
|
2050
|
-
//
|
|
2051
|
-
//
|
|
2052
|
-
//
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
//
|
|
2056
|
-
//
|
|
2076
|
+
// birth_corners_.erase(std::remove_if(birth_corners_.begin(),
|
|
2077
|
+
// birth_corners_.end(),
|
|
2078
|
+
// [](const std::vector<value_type> &bp) {
|
|
2079
|
+
// // return std::any_of(
|
|
2080
|
+
// // bp.begin(), bp.end(),
|
|
2081
|
+
// // [](float value) { return !std::isfinite(value); });
|
|
2082
|
+
// bp.size() == 0;
|
|
2083
|
+
// }),
|
|
2084
|
+
// birth_corners_.end());
|
|
2085
|
+
// birth_corners_.simplify();
|
|
2057
2086
|
// TODO : clean
|
|
2058
2087
|
}
|
|
2059
2088
|
|
|
@@ -2064,13 +2093,15 @@ inline void Summand<value_type>::complete_birth(const value_type precision) {
|
|
|
2064
2093
|
for (std::size_t i = 0; i < birth_corners_.num_generators(); i++) {
|
|
2065
2094
|
for (std::size_t j = i + 1; j < birth_corners_.num_generators(); j++) {
|
|
2066
2095
|
value_type dinf = d_inf(birth_corners_[i], birth_corners_[j]);
|
|
2067
|
-
if (dinf <
|
|
2096
|
+
if (dinf < .99 * precision) { // for machine error ?
|
|
2068
2097
|
_factorize_min(birth_corners_[i], birth_corners_[j]);
|
|
2069
|
-
birth_corners_[j]
|
|
2098
|
+
birth_corners_[j] = std::remove_reference_t<decltype(birth_corners_[j])>::inf();
|
|
2099
|
+
i++;
|
|
2070
2100
|
}
|
|
2071
2101
|
}
|
|
2072
2102
|
}
|
|
2073
|
-
|
|
2103
|
+
birth_corners_.simplify();
|
|
2104
|
+
// _clean(birth_corners_);
|
|
2074
2105
|
}
|
|
2075
2106
|
|
|
2076
2107
|
template <typename value_type>
|
|
@@ -2080,13 +2111,16 @@ inline void Summand<value_type>::complete_death(const value_type precision) {
|
|
|
2080
2111
|
for (std::size_t i = 0; i < death_corners_.num_generators(); i++) {
|
|
2081
2112
|
for (std::size_t j = i + 1; j < death_corners_.num_generators(); j++) {
|
|
2082
2113
|
value_type d = d_inf(death_corners_[i], death_corners_[j]);
|
|
2083
|
-
if (d <
|
|
2114
|
+
if (d < .99 * precision) {
|
|
2084
2115
|
_factorize_max(death_corners_[i], death_corners_[j]);
|
|
2085
|
-
death_corners_[j]
|
|
2116
|
+
death_corners_[j] = std::remove_reference_t<decltype(death_corners_[j])>::minus_inf();
|
|
2117
|
+
i++;
|
|
2086
2118
|
}
|
|
2087
2119
|
}
|
|
2088
2120
|
}
|
|
2089
|
-
|
|
2121
|
+
|
|
2122
|
+
death_corners_.simplify();
|
|
2123
|
+
// _clean(death_corners_);
|
|
2090
2124
|
}
|
|
2091
2125
|
|
|
2092
2126
|
template <typename value_type>
|
|
Binary file
|
|
@@ -14,6 +14,7 @@ import numpy as np
|
|
|
14
14
|
from typing import List
|
|
15
15
|
from joblib import Parallel, delayed
|
|
16
16
|
import sys
|
|
17
|
+
from warnings import warn
|
|
17
18
|
|
|
18
19
|
###########################################################################
|
|
19
20
|
## CPP CLASSES
|
|
@@ -56,15 +57,20 @@ def module_approximation_from_slicer(
|
|
|
56
57
|
bool threshold=False,
|
|
57
58
|
bool verbose=False,
|
|
58
59
|
list[float] direction = [],
|
|
60
|
+
bool warnings = True,
|
|
59
61
|
)->PyModule_type:
|
|
60
62
|
|
|
61
63
|
cdef Module[float] mod_f32
|
|
62
64
|
cdef Module[double] mod_f64
|
|
63
65
|
cdef intptr_t ptr
|
|
64
66
|
if not slicer.is_vine:
|
|
65
|
-
|
|
67
|
+
if warnings:
|
|
68
|
+
warn(r"(copy warning) Got a non-vine slicer as an input. Use `vineyard=True` to remove this copy.")
|
|
66
69
|
from multipers._slicer_meta import Slicer
|
|
67
70
|
slicer = Slicer(slicer, vineyard=True, backend="matrix")
|
|
71
|
+
if slicer.is_squeezed:
|
|
72
|
+
raise ValueError("Got a squeezed slicer. Should have been unsqueezed before !")
|
|
73
|
+
|
|
68
74
|
direction_ = np.asarray(direction, dtype=slicer.dtype)
|
|
69
75
|
if slicer.dtype == np.float32:
|
|
70
76
|
approx_mod = PyModule_f32()
|
|
@@ -89,14 +95,14 @@ def module_approximation(
|
|
|
89
95
|
input:Union[SimplexTreeMulti_type,Slicer_type, tuple],
|
|
90
96
|
box:Optional[np.ndarray]=None,
|
|
91
97
|
float max_error=-1,
|
|
92
|
-
int nlines=
|
|
98
|
+
int nlines=557,
|
|
93
99
|
slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
94
100
|
minpres:Optional[Literal["mpfree"]]=None,
|
|
95
101
|
degree:Optional[int]=None,
|
|
96
102
|
bool complete=True,
|
|
97
103
|
bool threshold=False,
|
|
98
104
|
bool verbose=False,
|
|
99
|
-
bool
|
|
105
|
+
bool ignore_warnings=False,
|
|
100
106
|
id="",
|
|
101
107
|
list[float] direction = [],
|
|
102
108
|
list[int] swap_box_coords = [],
|
|
@@ -156,16 +162,24 @@ def module_approximation(
|
|
|
156
162
|
if len(input) == 0:
|
|
157
163
|
return PyModule_f64()
|
|
158
164
|
if n_jobs <= 1:
|
|
159
|
-
modules = tuple(module_approximation(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose,
|
|
165
|
+
modules = tuple(module_approximation(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose, ignore_warnings, id, direction, swap_box_coords) for slicer in input)
|
|
160
166
|
else:
|
|
161
167
|
modules = tuple(Parallel(n_jobs=n_jobs, prefer="threads")(
|
|
162
|
-
delayed(module_approximation)(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose,
|
|
168
|
+
delayed(module_approximation)(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose, ignore_warnings, id, direction, swap_box_coords)
|
|
163
169
|
for slicer in input
|
|
164
170
|
))
|
|
165
|
-
|
|
171
|
+
box = modules[0].get_box()
|
|
172
|
+
mod = PyModule_f64().set_box(box)
|
|
166
173
|
for i,m in enumerate(modules):
|
|
167
174
|
mod.merge(m, input[i].minpres_degree)
|
|
168
175
|
return mod
|
|
176
|
+
if len(input) == 0:
|
|
177
|
+
return PyModule_f64()
|
|
178
|
+
if input.is_squeezed:
|
|
179
|
+
if not ignore_warnings:
|
|
180
|
+
warn("(copy warning) Got a squeezed input. ")
|
|
181
|
+
input = input.unsqueeze()
|
|
182
|
+
|
|
169
183
|
if box is None:
|
|
170
184
|
if is_simplextree_multi(input):
|
|
171
185
|
box = input.filtration_bounds()
|
|
@@ -190,11 +204,16 @@ def module_approximation(
|
|
|
190
204
|
if max_error <= 0:
|
|
191
205
|
max_error = (prod/nlines)**(1/(num_parameters-1))
|
|
192
206
|
|
|
193
|
-
if not
|
|
207
|
+
if not ignore_warnings and prod >= 10_000:
|
|
194
208
|
raise ValueError(f"""
|
|
195
209
|
Warning : the number of lines (around {np.round(prod)}) may be too high.
|
|
210
|
+
This may be due to extreme box or filtration bounds :
|
|
211
|
+
|
|
212
|
+
{box=}
|
|
213
|
+
|
|
196
214
|
Try to increase the precision parameter, or set `ignore_warning=True` to compute this module.
|
|
197
|
-
Returning the trivial module.
|
|
215
|
+
Returning the trivial module.
|
|
216
|
+
"""
|
|
198
217
|
)
|
|
199
218
|
if is_simplextree_multi(input):
|
|
200
219
|
from multipers._slicer_meta import Slicer
|
multipers/plots.py
CHANGED
|
@@ -137,6 +137,7 @@ def plot_signed_measure(signed_measure, threshold=None, ax=None, **plt_kwargs):
|
|
|
137
137
|
else:
|
|
138
138
|
pts_ = pts
|
|
139
139
|
threshold = np.max(np.ma.masked_invalid(pts_), axis=0)
|
|
140
|
+
threshold = np.max([threshold, [plt.gca().get_xlim()[1], plt.gca().get_ylim()[1]]], axis=0)
|
|
140
141
|
if isinstance(pts, np.ndarray):
|
|
141
142
|
pass
|
|
142
143
|
else:
|
|
@@ -254,7 +255,7 @@ def plot2d_PyModule(
|
|
|
254
255
|
dimension=-1,
|
|
255
256
|
separated=False,
|
|
256
257
|
min_persistence=0,
|
|
257
|
-
alpha
|
|
258
|
+
alpha=.8,
|
|
258
259
|
verbose=False,
|
|
259
260
|
save=False,
|
|
260
261
|
dpi=200,
|
|
Binary file
|
multipers/point_measure.pyx
CHANGED
|
@@ -89,6 +89,7 @@ def integrate_measure(
|
|
|
89
89
|
grid_strategy:str="regular",
|
|
90
90
|
resolution:int|list[int]=100,
|
|
91
91
|
bool return_grid=False,
|
|
92
|
+
bool plot=False,
|
|
92
93
|
**get_fitration_kwargs,
|
|
93
94
|
):
|
|
94
95
|
"""
|
|
@@ -126,6 +127,9 @@ def integrate_measure(
|
|
|
126
127
|
for i in range(num_pts):
|
|
127
128
|
cone = tuple(slice(c,r) for r,c in zip(resolution,pts_coords[:,i]))
|
|
128
129
|
out[cone] += weights[i]
|
|
130
|
+
if plot:
|
|
131
|
+
from multipers.plots import plot_surface
|
|
132
|
+
plot_surface(filtration_grid, out, discrete_surface=True)
|
|
129
133
|
if return_grid:
|
|
130
134
|
return out,filtration_grid
|
|
131
135
|
return out
|
|
@@ -211,7 +215,7 @@ def zero_out_sm(pts,weights, mass_default):
|
|
|
211
215
|
C = np.concatenate([C, np.ones((C.shape[0],1))], axis=1).astype(np.bool_)
|
|
212
216
|
|
|
213
217
|
# signs of each corner
|
|
214
|
-
Cw = 1-2*((~C).sum(axis=1)
|
|
218
|
+
Cw = 1-2*((~C).sum(axis=1) & 1)
|
|
215
219
|
|
|
216
220
|
# something useless in the end to ensure that the shape is correct (as we added 1 in pts)
|
|
217
221
|
mass_default = np.concatenate([mass_default,[np.nan]])
|
|
@@ -299,7 +303,7 @@ def barcode_from_rank_sm(
|
|
|
299
303
|
return out
|
|
300
304
|
|
|
301
305
|
|
|
302
|
-
def estimate_rank_from_rank_sm(sm:tuple, a, b)
|
|
306
|
+
def estimate_rank_from_rank_sm(sm:tuple, a, b)->np.int64:
|
|
303
307
|
"""
|
|
304
308
|
Given a rank signed measure (sm) and two points (a) and (b),
|
|
305
309
|
estimates the rank between these two points.
|
|
Binary file
|
multipers/simplex_tree_multi.pxd
CHANGED
|
@@ -118,6 +118,7 @@ cdef extern from "Simplex_tree_multi_interface.h" namespace "Gudhi::multiparamet
|
|
|
118
118
|
void to_std_linear_projection(intptr_t, vector[double]) nogil
|
|
119
119
|
void squeeze_filtration_inplace(vector[vector[double]] &, bool) nogil
|
|
120
120
|
void squeeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
121
|
+
void unsqueeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
121
122
|
vector[vector[vector[value_type]]] get_filtration_values(const vector[int]&) nogil
|
|
122
123
|
|
|
123
124
|
|