multipers 2.3.0__cp311-cp311-win_amd64.whl → 2.3.1__cp311-cp311-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/{ml/convolutions.py → filtrations/density.py} +45 -2
- multipers/filtrations/filtrations.py +2 -2
- multipers/function_rips.cp311-win_amd64.pyd +0 -0
- multipers/grids.cp311-win_amd64.pyd +0 -0
- multipers/gudhi/Simplex_tree_multi_interface.h +1 -1
- multipers/gudhi/gudhi/One_critical_filtration.h +2 -1
- multipers/gudhi/mma_interface_h0.h +1 -1
- multipers/gudhi/mma_interface_matrix.h +8 -1
- multipers/gudhi/naive_merge_tree.h +1 -1
- multipers/gudhi/truc.h +82 -15
- multipers/io.cp311-win_amd64.pyd +0 -0
- multipers/io.pyx +14 -11
- multipers/ml/point_clouds.py +2 -2
- multipers/ml/signed_measures.py +3 -3
- multipers/mma_structures.cp311-win_amd64.pyd +0 -0
- multipers/mma_structures.pyx +0 -4
- multipers/mma_structures.pyx.tp +0 -2
- multipers/multiparameter_module_approximation/approximation.h +4 -2
- multipers/multiparameter_module_approximation.cp311-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +3 -1
- multipers/plots.py +1 -1
- multipers/point_measure.cp311-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.cp311-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.pyx +97 -33
- multipers/simplex_tree_multi.pyx.tp +13 -5
- multipers/slicer.cp311-win_amd64.pyd +0 -0
- multipers/slicer.pxd +220 -100
- multipers/slicer.pxd.tp +5 -2
- multipers/slicer.pyx +484 -204
- multipers/slicer.pyx.tp +16 -9
- multipers/tensor/tensor.h +1 -1
- multipers/torch/rips_density.py +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.1.dist-info}/METADATA +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.1.dist-info}/RECORD +37 -37
- {multipers-2.3.0.dist-info → multipers-2.3.1.dist-info}/WHEEL +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.1.dist-info}/LICENSE +0 -0
- {multipers-2.3.0.dist-info → multipers-2.3.1.dist-info}/top_level.txt +0 -0
|
@@ -180,9 +180,10 @@ def _pts_convolution_pykeops(
|
|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
def gaussian_kernel(x_i, y_j, bandwidth):
|
|
183
|
+
D = x_i.shape[-1]
|
|
183
184
|
exponent = -(((x_i - y_j) / bandwidth) ** 2).sum(dim=-1) / 2
|
|
184
185
|
# float is necessary for some reason (pykeops fails)
|
|
185
|
-
kernel = (exponent).exp() / (bandwidth
|
|
186
|
+
kernel = (exponent).exp() / float((bandwidth*np.sqrt(2 * np.pi))**D)
|
|
186
187
|
return kernel
|
|
187
188
|
|
|
188
189
|
|
|
@@ -339,7 +340,7 @@ class KDE:
|
|
|
339
340
|
kernel *= w
|
|
340
341
|
if return_kernel:
|
|
341
342
|
return kernel
|
|
342
|
-
density_estimation = kernel.sum(dim=0).
|
|
343
|
+
density_estimation = kernel.sum(dim=0).squeeze() / kernel.shape[0] # mean
|
|
343
344
|
return (
|
|
344
345
|
self._backend.log(density_estimation)
|
|
345
346
|
if self.return_log
|
|
@@ -497,6 +498,48 @@ class DTM:
|
|
|
497
498
|
return DTMs
|
|
498
499
|
|
|
499
500
|
|
|
501
|
+
## code taken from pykeops doc (https://www.kernel-operations.io/keops/_auto_benchmarks/benchmark_KNN.html)
|
|
502
|
+
class KNNmean:
|
|
503
|
+
def __init__(self, k: int, metric: str = "euclidean"):
|
|
504
|
+
self.k = k
|
|
505
|
+
self.metric = metric
|
|
506
|
+
self._KNN_fun = None
|
|
507
|
+
self._x = None
|
|
508
|
+
|
|
509
|
+
def fit(self, x):
|
|
510
|
+
if isinstance(x, np.ndarray):
|
|
511
|
+
from pykeops.numpy import Vi, Vj
|
|
512
|
+
else:
|
|
513
|
+
import torch
|
|
514
|
+
|
|
515
|
+
assert isinstance(x, torch.Tensor), "Backend has to be numpy or torch"
|
|
516
|
+
from pykeops.torch import Vi, Vj
|
|
517
|
+
|
|
518
|
+
D = x.shape[1]
|
|
519
|
+
X_i = Vi(0, D)
|
|
520
|
+
X_j = Vj(1, D)
|
|
521
|
+
|
|
522
|
+
# Symbolic distance matrix:
|
|
523
|
+
if self.metric == "euclidean":
|
|
524
|
+
D_ij = ((X_i - X_j) ** 2).sum(-1)
|
|
525
|
+
elif self.metric == "manhattan":
|
|
526
|
+
D_ij = (X_i - X_j).abs().sum(-1)
|
|
527
|
+
elif self.metric == "angular":
|
|
528
|
+
D_ij = -(X_i | X_j)
|
|
529
|
+
elif self.metric == "hyperbolic":
|
|
530
|
+
D_ij = ((X_i - X_j) ** 2).sum(-1) / (X_i[0] * X_j[0])
|
|
531
|
+
else:
|
|
532
|
+
raise NotImplementedError(f"The '{self.metric}' distance is not supported.")
|
|
533
|
+
|
|
534
|
+
self._x = x
|
|
535
|
+
self._KNN_fun = D_ij.Kmin(self.k, dim=1)
|
|
536
|
+
return self
|
|
537
|
+
|
|
538
|
+
def score_samples(self, x):
|
|
539
|
+
assert self._x is not None and self._KNN_fun is not None, "Fit first."
|
|
540
|
+
return self._KNN_fun(x, self._x).sum(axis=1) / self.k
|
|
541
|
+
|
|
542
|
+
|
|
500
543
|
# def _pts_convolution_sparse(pts:np.ndarray, pts_weights:np.ndarray, filtration_grid:Iterable[np.ndarray], kernel="gaussian", bandwidth=0.1, **more_kde_args):
|
|
501
544
|
# """
|
|
502
545
|
# Old version of `convolution_signed_measures`. Scikitlearn's convolution is slower than the code above.
|
|
@@ -7,13 +7,13 @@ from numpy.typing import ArrayLike
|
|
|
7
7
|
from scipy.spatial import KDTree
|
|
8
8
|
from scipy.spatial.distance import cdist
|
|
9
9
|
|
|
10
|
-
from multipers.
|
|
10
|
+
from multipers.filtrations.density import DTM, available_kernels
|
|
11
11
|
from multipers.simplex_tree_multi import SimplexTreeMulti, SimplexTreeMulti_type
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
14
|
import pykeops
|
|
15
15
|
|
|
16
|
-
from multipers.
|
|
16
|
+
from multipers.filtrations.density import KDE
|
|
17
17
|
except ImportError:
|
|
18
18
|
from sklearn.neighbors import KernelDensity
|
|
19
19
|
from warnings import warn
|
|
Binary file
|
|
Binary file
|
|
@@ -165,7 +165,7 @@ class Simplex_tree_multi_interface
|
|
|
165
165
|
|
|
166
166
|
void compute_extended_filtration() { throw std::logic_error("Incompatible with multipers"); }
|
|
167
167
|
|
|
168
|
-
Simplex_tree_multi_interface *collapse_edges(int nb_collapse_iteration) {
|
|
168
|
+
Simplex_tree_multi_interface *collapse_edges([[maybe_unused]] int nb_collapse_iteration) {
|
|
169
169
|
throw std::logic_error("Incompatible with multipers");
|
|
170
170
|
}
|
|
171
171
|
|
|
@@ -1039,7 +1039,8 @@ class One_critical_filtration : public std::vector<T> {
|
|
|
1039
1039
|
std::lower_bound(filtration.begin(),
|
|
1040
1040
|
filtration.end(),
|
|
1041
1041
|
static_cast<typename oned_array::value_type>(Base::operator[](parameter))));
|
|
1042
|
-
|
|
1042
|
+
int num_filtration_values = filtration.size();
|
|
1043
|
+
d = d == num_filtration_values ? std::max(num_filtration_values - 1,0) : d;
|
|
1043
1044
|
Base::operator[](parameter) = coordinate ? static_cast<T>(d) : static_cast<T>(filtration[d]);
|
|
1044
1045
|
}
|
|
1045
1046
|
}
|
|
@@ -39,7 +39,7 @@ class Persistence_backend_h0 {
|
|
|
39
39
|
using cycle_type = std::vector<unsigned int>;
|
|
40
40
|
static const bool is_vine = true;
|
|
41
41
|
|
|
42
|
-
std::vector<cycle_type> get_representative_cycles(bool update = true) const { throw "Unimplemented"; }
|
|
42
|
+
std::vector<cycle_type> get_representative_cycles([[maybe_unused]] bool update = true) const { throw "Unimplemented"; }
|
|
43
43
|
|
|
44
44
|
class Barcode_iterator : public boost::iterator_facade<Barcode_iterator, const Bar &, boost::forward_traversal_tag> {
|
|
45
45
|
public:
|
|
@@ -60,6 +60,13 @@ struct No_vine_multi_persistence_options : Gudhi::persistence_matrix::Default_op
|
|
|
60
60
|
static const bool has_vine_update = false;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
template <Gudhi::persistence_matrix::Column_types column_type = Gudhi::persistence_matrix::Column_types::INTRUSIVE_SET>
|
|
64
|
+
struct fix_presentation_options : Gudhi::persistence_matrix::Default_options<column_type, true> {
|
|
65
|
+
using Index = std::uint32_t;
|
|
66
|
+
static const bool has_map_column_container = true;
|
|
67
|
+
static const bool has_removable_columns = true; // WARN : idx will change if map is not true
|
|
68
|
+
};
|
|
69
|
+
|
|
63
70
|
template <class Matrix_options, class Boundary_matrix_type>
|
|
64
71
|
class Persistence_backend_matrix {
|
|
65
72
|
public:
|
|
@@ -228,7 +235,7 @@ class Persistence_backend_matrix {
|
|
|
228
235
|
|
|
229
236
|
inline Barcode get_barcode() { return Barcode(matrix_, permutation_); }
|
|
230
237
|
|
|
231
|
-
inline std::size_t size() { return this->matrix_.get_number_of_columns(); }
|
|
238
|
+
inline std::size_t size() const { return this->matrix_.get_number_of_columns(); }
|
|
232
239
|
|
|
233
240
|
inline friend std::ostream &operator<<(std::ostream &stream, Persistence_backend_matrix &structure) {
|
|
234
241
|
stream << "[\n";
|
|
@@ -314,7 +314,7 @@ class Naive_merge_forest {
|
|
|
314
314
|
struct Barcode {
|
|
315
315
|
Barcode() {}
|
|
316
316
|
|
|
317
|
-
Barcode(int numberOfSimplices, int numberOfVertices)
|
|
317
|
+
Barcode(int numberOfSimplices, [[maybe_unused]] int numberOfVertices)
|
|
318
318
|
: barcode_(numberOfSimplices), positionToBar_(numberOfSimplices), nextBarIndex_(0) {}
|
|
319
319
|
|
|
320
320
|
friend void swap(Barcode &mf1, Barcode &mf2) {
|
multipers/gudhi/truc.h
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <algorithm>
|
|
7
7
|
#include <boost/mpl/aux_/na_fwd.hpp>
|
|
8
8
|
#include <cassert>
|
|
9
|
+
#include <csignal>
|
|
9
10
|
#include <cstddef>
|
|
10
11
|
#include <cstdint>
|
|
11
12
|
// #include <gudhi/Simplex_tree/multi_filtrations/Finitely_critical_filtrations.h>
|
|
@@ -116,6 +117,19 @@ class PresentationStructure {
|
|
|
116
117
|
return idx;
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
PresentationStructure permute(const std::vector<index_type> &order) const {
|
|
121
|
+
std::vector<std::vector<index_type>> new_generators(generators.size());
|
|
122
|
+
std::vector<int> new_generator_dimensions(generator_dimensions.size());
|
|
123
|
+
for (std::size_t i = 0; i < order.size(); i++) {
|
|
124
|
+
new_generators[i] = std::vector<index_type>(generators[order[i]].size());
|
|
125
|
+
for (std::size_t j = 0; j < generators[order[i]].size(); j++) {
|
|
126
|
+
new_generators[i][j] = order[generators[order[i]][j]];
|
|
127
|
+
}
|
|
128
|
+
new_generator_dimensions[i] = generator_dimensions[order[i]];
|
|
129
|
+
}
|
|
130
|
+
return PresentationStructure(new_generators, new_generator_dimensions);
|
|
131
|
+
}
|
|
132
|
+
|
|
119
133
|
private:
|
|
120
134
|
std::vector<std::vector<index_type>> generators;
|
|
121
135
|
std::vector<int> generator_dimensions;
|
|
@@ -184,7 +198,7 @@ class SimplicialStructure {
|
|
|
184
198
|
|
|
185
199
|
inline unsigned int max_dimension() const { return max_dimension_; }
|
|
186
200
|
|
|
187
|
-
int prune_above_dimension(int dim) { throw; }
|
|
201
|
+
int prune_above_dimension([[maybe_unused]] int dim) { throw "Not implemented"; }
|
|
188
202
|
|
|
189
203
|
private:
|
|
190
204
|
std::vector<std::vector<index_type>> boundaries;
|
|
@@ -238,18 +252,67 @@ class Truc {
|
|
|
238
252
|
std::iota(generator_order.begin(), generator_order.end(), 0); // range
|
|
239
253
|
}
|
|
240
254
|
|
|
241
|
-
Truc()
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
persistence = other.persistence;
|
|
248
|
-
filtration_container = other.filtration_container;
|
|
255
|
+
Truc(const Truc &other)
|
|
256
|
+
: generator_filtration_values(other.generator_filtration_values),
|
|
257
|
+
generator_order(other.generator_order),
|
|
258
|
+
structure(other.structure),
|
|
259
|
+
filtration_container(other.filtration_container),
|
|
260
|
+
persistence(other.persistence) {
|
|
249
261
|
persistence._update_permutation_ptr(generator_order);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
Truc &operator=(Truc other) {
|
|
265
|
+
if (this != &other) {
|
|
266
|
+
generator_filtration_values = other.generator_filtration_values;
|
|
267
|
+
generator_order = other.generator_order;
|
|
268
|
+
structure = other.structure;
|
|
269
|
+
filtration_container = other.filtration_container;
|
|
270
|
+
persistence = other.persistence;
|
|
271
|
+
persistence._update_permutation_ptr(generator_order);
|
|
272
|
+
}
|
|
250
273
|
return *this;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
Truc() {};
|
|
277
|
+
|
|
278
|
+
inline bool dimension_order(const index_type &i, const index_type &j) const {
|
|
279
|
+
return structure.dimension(i) < structure.dimension(j);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
inline bool colexical_order(const index_type &i, const index_type &j) const {
|
|
283
|
+
if (structure.dimension(i) > structure.dimension(j)) return false;
|
|
284
|
+
if (structure.dimension(i) < structure.dimension(j)) return true;
|
|
285
|
+
if constexpr (MultiFiltration::is_multicritical()) // TODO : this may not be the best
|
|
286
|
+
throw "Not implemented in the multicritical case";
|
|
287
|
+
|
|
288
|
+
for (int idx = generator_filtration_values[i].num_parameters() - 1; idx >= 0; --idx) {
|
|
289
|
+
if (generator_filtration_values[i][idx] < generator_filtration_values[j][idx])
|
|
290
|
+
return true;
|
|
291
|
+
else if (generator_filtration_values[i][idx] > generator_filtration_values[j][idx])
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
251
295
|
};
|
|
252
296
|
|
|
297
|
+
|
|
298
|
+
template <class Fun>
|
|
299
|
+
inline Truc rearange_sort(const Fun&& fun) const {
|
|
300
|
+
std::vector<index_type> permutation(generator_order.size());
|
|
301
|
+
std::iota(permutation.begin(), permutation.end(), 0);
|
|
302
|
+
std::sort(permutation.begin(), permutation.end(), [&](std::size_t i, std::size_t j) {
|
|
303
|
+
return fun(i, j);
|
|
304
|
+
});
|
|
305
|
+
std::vector<MultiFiltration> new_filtration(generator_filtration_values.size());
|
|
306
|
+
for (std::size_t i = 0; i < generator_filtration_values.size(); i++) {
|
|
307
|
+
new_filtration[i] = generator_filtration_values[permutation[i]];
|
|
308
|
+
}
|
|
309
|
+
return Truc(structure.permute(permutation), new_filtration);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
Truc colexical_rearange() const {
|
|
313
|
+
return rearange_sort([this](std::size_t i, std::size_t j) { return this->colexical_order(i, j); });
|
|
314
|
+
}
|
|
315
|
+
|
|
253
316
|
template <bool ignore_inf>
|
|
254
317
|
std::vector<std::pair<int, std::vector<index_type>>> get_current_boundary_matrix() {
|
|
255
318
|
std::vector<index_type> permutation(generator_order.size());
|
|
@@ -375,7 +438,7 @@ class Truc {
|
|
|
375
438
|
return PersBackend(structure, out_gen_order);
|
|
376
439
|
}
|
|
377
440
|
|
|
378
|
-
inline
|
|
441
|
+
inline bool has_persistence() const { return this->persistence.size(); };
|
|
379
442
|
|
|
380
443
|
inline void compute_persistence(const bool ignore_inf = true) {
|
|
381
444
|
this->persistence = this->compute_persistence_out(
|
|
@@ -718,7 +781,7 @@ class Truc {
|
|
|
718
781
|
|
|
719
782
|
inline TrucThread weak_copy() const { return TrucThread(*truc_ptr); }
|
|
720
783
|
|
|
721
|
-
inline
|
|
784
|
+
inline bool has_persistence() const { return this->persistence.size(); };
|
|
722
785
|
|
|
723
786
|
inline const PersBackend &get_persistence() const { return persistence; }
|
|
724
787
|
|
|
@@ -827,19 +890,23 @@ class Truc {
|
|
|
827
890
|
|
|
828
891
|
// FOR Python interface, but I'm not fan. Todo: do the lambda function in
|
|
829
892
|
// cython?
|
|
830
|
-
inline std::vector<split_barcode> persistence_on_lines(const std::vector<std::vector<value_type>> &basepoints
|
|
893
|
+
inline std::vector<split_barcode> persistence_on_lines(const std::vector<std::vector<value_type>> &basepoints,
|
|
894
|
+
bool ignore_inf) {
|
|
831
895
|
return barcodes(
|
|
832
896
|
[](const std::vector<value_type> &basepoint) { return Gudhi::multi_persistence::Line<value_type>(basepoint); },
|
|
833
|
-
basepoints
|
|
897
|
+
basepoints,
|
|
898
|
+
ignore_inf);
|
|
834
899
|
}
|
|
835
900
|
|
|
836
901
|
inline std::vector<split_barcode> persistence_on_lines(
|
|
837
|
-
const std::vector<std::pair<std::vector<value_type>, std::vector<value_type>>> &bp_dirs
|
|
902
|
+
const std::vector<std::pair<std::vector<value_type>, std::vector<value_type>>> &bp_dirs,
|
|
903
|
+
bool ignore_inf) {
|
|
838
904
|
return barcodes(
|
|
839
905
|
[](const std::pair<std::vector<value_type>, std::vector<value_type>> &bpdir) {
|
|
840
906
|
return Gudhi::multi_persistence::Line<value_type>(bpdir.first, bpdir.second);
|
|
841
907
|
},
|
|
842
|
-
bp_dirs
|
|
908
|
+
bp_dirs,
|
|
909
|
+
ignore_inf);
|
|
843
910
|
}
|
|
844
911
|
|
|
845
912
|
void build_from_scc_file(const std::string &inFilePath,
|
multipers/io.cp311-win_amd64.pyd
CHANGED
|
Binary file
|
multipers/io.pyx
CHANGED
|
@@ -15,7 +15,7 @@ cimport cython
|
|
|
15
15
|
# from multipers.filtration_conversions cimport *
|
|
16
16
|
# from multipers.mma_structures cimport boundary_matrix,float,pair,vector,intptr_t
|
|
17
17
|
# cimport numpy as cnp
|
|
18
|
-
|
|
18
|
+
current_doc_url = "https://davidlapous.github.io/multipers/"
|
|
19
19
|
doc_soft_urls = {
|
|
20
20
|
"mpfree":"https://bitbucket.org/mkerber/mpfree/",
|
|
21
21
|
"multi_chunk":"",
|
|
@@ -27,6 +27,8 @@ doc_soft_easy_install = {
|
|
|
27
27
|
```sh
|
|
28
28
|
git clone {doc_soft_urls["mpfree"]}
|
|
29
29
|
cd mpfree
|
|
30
|
+
cmake . --fresh
|
|
31
|
+
make
|
|
30
32
|
sudo cp mpfree /usr/bin/
|
|
31
33
|
cd ..
|
|
32
34
|
rm -rf mpfree
|
|
@@ -36,6 +38,8 @@ rm -rf mpfree
|
|
|
36
38
|
```sh
|
|
37
39
|
git clone {doc_soft_urls["multi_chunk"]}
|
|
38
40
|
cd multi_chunk
|
|
41
|
+
cmake . --fresh
|
|
42
|
+
make
|
|
39
43
|
sudo cp multi_chunk /usr/bin/
|
|
40
44
|
cd ..
|
|
41
45
|
rm -rf multi_chunk
|
|
@@ -45,6 +49,8 @@ rm -rf multi_chunk
|
|
|
45
49
|
```sh
|
|
46
50
|
git clone {doc_soft_urls["function_delaunay"]}
|
|
47
51
|
cd function_delaunay
|
|
52
|
+
cmake . --fresh
|
|
53
|
+
make
|
|
48
54
|
sudo cp main /usr/bin/function_delaunay
|
|
49
55
|
cd ..
|
|
50
56
|
rm -rf function_delaunay
|
|
@@ -65,7 +71,6 @@ doc_soft_easy_install = defaultdict(lambda:"<Unknown>", doc_soft_easy_install)
|
|
|
65
71
|
|
|
66
72
|
available_reduce_softs = Literal["mpfree","multi_chunk","2pac"]
|
|
67
73
|
|
|
68
|
-
|
|
69
74
|
def _path_init(soft:str|os.PathLike):
|
|
70
75
|
a = which(f"./{soft}")
|
|
71
76
|
b = which(f"{soft}")
|
|
@@ -222,12 +227,14 @@ def _init_external_softwares(requires=[]):
|
|
|
222
227
|
if pathes[soft] is None:
|
|
223
228
|
global doc_soft_urls
|
|
224
229
|
raise ValueError(f"""
|
|
225
|
-
Did not
|
|
230
|
+
Did not find {soft}.
|
|
226
231
|
Install it from {doc_soft_urls[soft]}, and put it in your current directory,
|
|
227
232
|
or in you $PATH.
|
|
233
|
+
Documentation is available here: {current_doc_url}compilation.html#external-libraries
|
|
228
234
|
For instance:
|
|
229
235
|
{doc_soft_easy_install[soft]}
|
|
230
236
|
""")
|
|
237
|
+
_init_external_softwares()
|
|
231
238
|
def _check_available(soft:str):
|
|
232
239
|
_init_external_softwares()
|
|
233
240
|
return pathes.get(soft,None) is not None
|
|
@@ -255,8 +262,7 @@ def scc_reduce_from_str(
|
|
|
255
262
|
backend: "mpfree", "multi_chunk" or "2pac"
|
|
256
263
|
"""
|
|
257
264
|
global pathes, input_path, output_path
|
|
258
|
-
|
|
259
|
-
_init_external_softwares(requires=[backend])
|
|
265
|
+
assert _check_available(backend), f"Backend {backend} is not available."
|
|
260
266
|
|
|
261
267
|
|
|
262
268
|
resolution_str = "--resolution" if full_resolution else ""
|
|
@@ -323,8 +329,7 @@ def scc_reduce_from_str_to_slicer(
|
|
|
323
329
|
backend: "mpfree", "multi_chunk" or "2pac"
|
|
324
330
|
"""
|
|
325
331
|
global pathes, input_path, output_path
|
|
326
|
-
|
|
327
|
-
_init_external_softwares(requires=[backend])
|
|
332
|
+
assert _check_available(backend), f"Backend {backend} is not available."
|
|
328
333
|
|
|
329
334
|
|
|
330
335
|
resolution_str = "--resolution" if full_resolution else ""
|
|
@@ -443,8 +448,7 @@ def function_delaunay_presentation(
|
|
|
443
448
|
id = str(threading.get_native_id())
|
|
444
449
|
global input_path, output_path, pathes
|
|
445
450
|
backend = "function_delaunay"
|
|
446
|
-
|
|
447
|
-
_init_external_softwares(requires=[backend])
|
|
451
|
+
assert _check_available(backend), f"Backend {backend} is not available."
|
|
448
452
|
|
|
449
453
|
to_write = np.concatenate([point_cloud, function_values.reshape(-1,1)], axis=1)
|
|
450
454
|
np.savetxt(input_path+id,to_write,delimiter=' ')
|
|
@@ -492,8 +496,7 @@ def function_delaunay_presentation_to_slicer(
|
|
|
492
496
|
id = str(threading.get_native_id())
|
|
493
497
|
global input_path, output_path, pathes
|
|
494
498
|
backend = "function_delaunay"
|
|
495
|
-
|
|
496
|
-
_init_external_softwares(requires=[backend])
|
|
499
|
+
assert _check_available(backend), f"Backend {backend} is not available."
|
|
497
500
|
|
|
498
501
|
to_write = np.concatenate([point_cloud, function_values.reshape(-1,1)], axis=1)
|
|
499
502
|
np.savetxt(input_path+id,to_write,delimiter=' ')
|
multipers/ml/point_clouds.py
CHANGED
|
@@ -10,7 +10,7 @@ from tqdm import tqdm
|
|
|
10
10
|
|
|
11
11
|
import multipers as mp
|
|
12
12
|
import multipers.slicer as mps
|
|
13
|
-
from multipers.
|
|
13
|
+
from multipers.filtrations.density import DTM, KDE, available_kernels
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class PointCloud2FilteredComplex(BaseEstimator, TransformerMixin):
|
|
@@ -176,7 +176,7 @@ class PointCloud2FilteredComplex(BaseEstimator, TransformerMixin):
|
|
|
176
176
|
st = alpha_complex.create_simplex_tree(max_alpha_square=self._threshold**2)
|
|
177
177
|
vertices = np.array([i for (i,), _ in st.get_skeleton(0)])
|
|
178
178
|
new_points = np.asarray(
|
|
179
|
-
[alpha_complex.get_point(i) for i in vertices]
|
|
179
|
+
[alpha_complex.get_point(int(i)) for i in vertices]
|
|
180
180
|
) # Seems to be unsafe for some reason
|
|
181
181
|
# new_points = x
|
|
182
182
|
st = mp.simplex_tree_multi.SimplexTreeMulti(
|
multipers/ml/signed_measures.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections.abc import
|
|
1
|
+
from collections.abc import Iterable, Sequence
|
|
2
2
|
from itertools import product
|
|
3
3
|
from typing import Optional, Union
|
|
4
4
|
|
|
@@ -10,8 +10,8 @@ from tqdm import tqdm
|
|
|
10
10
|
|
|
11
11
|
import multipers as mp
|
|
12
12
|
from multipers.grids import compute_grid as reduce_grid
|
|
13
|
-
from multipers.
|
|
14
|
-
from multipers.point_measure import
|
|
13
|
+
from multipers.filtrations.density import available_kernels, convolution_signed_measures
|
|
14
|
+
from multipers.point_measure import rank_decomposition_by_rectangles, signed_betti
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class FilteredComplex2SignedMeasure(BaseEstimator, TransformerMixin):
|
|
Binary file
|
multipers/mma_structures.pyx
CHANGED
|
@@ -580,7 +580,6 @@ cdef class PyModule_f64:
|
|
|
580
580
|
cdef Box[double] c_box = Box[double](box)
|
|
581
581
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
582
582
|
if plot:
|
|
583
|
-
plt.figure()
|
|
584
583
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
585
584
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
586
585
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -614,7 +613,6 @@ cdef class PyModule_f64:
|
|
|
614
613
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[double](box), resolution))
|
|
615
614
|
if plot:
|
|
616
615
|
to_plot = np.sum(out, axis=0)
|
|
617
|
-
plt.figure()
|
|
618
616
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
619
617
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
620
618
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -1532,7 +1530,6 @@ cdef class PyModule_f32:
|
|
|
1532
1530
|
cdef Box[float] c_box = Box[float](box)
|
|
1533
1531
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
1534
1532
|
if plot:
|
|
1535
|
-
plt.figure()
|
|
1536
1533
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
1537
1534
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
1538
1535
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -1566,7 +1563,6 @@ cdef class PyModule_f32:
|
|
|
1566
1563
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[float](box), resolution))
|
|
1567
1564
|
if plot:
|
|
1568
1565
|
to_plot = np.sum(out, axis=0)
|
|
1569
|
-
plt.figure()
|
|
1570
1566
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
1571
1567
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
1572
1568
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
multipers/mma_structures.pyx.tp
CHANGED
|
@@ -602,7 +602,6 @@ cdef class PyModule_{{SHORT}}:
|
|
|
602
602
|
cdef Box[{{CTYPE}}] c_box = Box[{{CTYPE}}](box)
|
|
603
603
|
out = np.array(self.cmod.get_landscape(degree, k, c_box, resolution))
|
|
604
604
|
if plot:
|
|
605
|
-
plt.figure()
|
|
606
605
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
607
606
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
608
607
|
plt.imshow(out.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -636,7 +635,6 @@ cdef class PyModule_{{SHORT}}:
|
|
|
636
635
|
out = np.array(self.cmod.get_landscapes(degree, ks, Box[{{CTYPE}}](box), resolution))
|
|
637
636
|
if plot:
|
|
638
637
|
to_plot = np.sum(out, axis=0)
|
|
639
|
-
plt.figure()
|
|
640
638
|
aspect = (box[1][0]-box[0][0]) / (box[1][1]-box[0][1])
|
|
641
639
|
extent = [box[0][0], box[1][0], box[0][1], box[1][1]]
|
|
642
640
|
plt.imshow(to_plot.T, origin="lower", extent=extent, aspect=aspect)
|
|
@@ -2064,9 +2064,10 @@ inline void Summand<value_type>::complete_birth(const value_type precision) {
|
|
|
2064
2064
|
for (std::size_t i = 0; i < birth_corners_.num_generators(); i++) {
|
|
2065
2065
|
for (std::size_t j = i + 1; j < birth_corners_.num_generators(); j++) {
|
|
2066
2066
|
value_type dinf = d_inf(birth_corners_[i], birth_corners_[j]);
|
|
2067
|
-
if (dinf <
|
|
2067
|
+
if (dinf < .99 * precision) { // for machine error ?
|
|
2068
2068
|
_factorize_min(birth_corners_[i], birth_corners_[j]);
|
|
2069
2069
|
birth_corners_[j].clear();
|
|
2070
|
+
i++;
|
|
2070
2071
|
}
|
|
2071
2072
|
}
|
|
2072
2073
|
}
|
|
@@ -2080,9 +2081,10 @@ inline void Summand<value_type>::complete_death(const value_type precision) {
|
|
|
2080
2081
|
for (std::size_t i = 0; i < death_corners_.num_generators(); i++) {
|
|
2081
2082
|
for (std::size_t j = i + 1; j < death_corners_.num_generators(); j++) {
|
|
2082
2083
|
value_type d = d_inf(death_corners_[i], death_corners_[j]);
|
|
2083
|
-
if (d <
|
|
2084
|
+
if (d < .99 * precision) {
|
|
2084
2085
|
_factorize_max(death_corners_[i], death_corners_[j]);
|
|
2085
2086
|
death_corners_[j].clear();
|
|
2087
|
+
i++;
|
|
2086
2088
|
}
|
|
2087
2089
|
}
|
|
2088
2090
|
}
|
|
Binary file
|
|
@@ -89,7 +89,7 @@ def module_approximation(
|
|
|
89
89
|
input:Union[SimplexTreeMulti_type,Slicer_type, tuple],
|
|
90
90
|
box:Optional[np.ndarray]=None,
|
|
91
91
|
float max_error=-1,
|
|
92
|
-
int nlines=
|
|
92
|
+
int nlines=557,
|
|
93
93
|
slicer_backend:Literal["matrix","clement","graph"]="matrix",
|
|
94
94
|
minpres:Optional[Literal["mpfree"]]=None,
|
|
95
95
|
degree:Optional[int]=None,
|
|
@@ -166,6 +166,8 @@ def module_approximation(
|
|
|
166
166
|
for i,m in enumerate(modules):
|
|
167
167
|
mod.merge(m, input[i].minpres_degree)
|
|
168
168
|
return mod
|
|
169
|
+
if len(input) == 0:
|
|
170
|
+
return PyModule_f64()
|
|
169
171
|
if box is None:
|
|
170
172
|
if is_simplextree_multi(input):
|
|
171
173
|
box = input.filtration_bounds()
|
multipers/plots.py
CHANGED
|
Binary file
|
|
Binary file
|