multipers 2.0.3__tar.gz → 2.0.4__tar.gz

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.

Files changed (94) hide show
  1. {multipers-2.0.3/multipers.egg-info → multipers-2.0.4}/PKG-INFO +1 -1
  2. {multipers-2.0.3 → multipers-2.0.4}/multipers/_signed_measure_meta.py +79 -65
  3. {multipers-2.0.3 → multipers-2.0.4}/multipers/_slicer_meta.py +1 -0
  4. {multipers-2.0.3 → multipers-2.0.4}/multipers/function_rips.cpp +155 -155
  5. {multipers-2.0.3 → multipers-2.0.4}/multipers/grids.cpp +155 -155
  6. {multipers-2.0.3 → multipers-2.0.4}/multipers/io.cpp +2387 -2140
  7. {multipers-2.0.3 → multipers-2.0.4}/multipers/io.pyx +11 -0
  8. {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.cpp +155 -155
  9. {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation.cpp +155 -155
  10. {multipers-2.0.3 → multipers-2.0.4}/multipers/point_measure_integration.cpp +155 -155
  11. {multipers-2.0.3 → multipers-2.0.4}/multipers/rank_invariant.cpp +712 -861
  12. multipers-2.0.4/multipers/rank_invariant.pyx +86 -0
  13. {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.cpp +449 -242
  14. {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.pyx +1 -1
  15. {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.cpp +37869 -35125
  16. {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.pyx +313 -109
  17. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/__init__.py +9 -6
  18. multipers-2.0.4/multipers/tests/test_signed_measure.py +86 -0
  19. {multipers-2.0.3 → multipers-2.0.4/multipers.egg-info}/PKG-INFO +1 -1
  20. {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/SOURCES.txt +1 -0
  21. {multipers-2.0.3 → multipers-2.0.4}/setup.py +1 -1
  22. multipers-2.0.3/multipers/rank_invariant.pyx +0 -224
  23. {multipers-2.0.3 → multipers-2.0.4}/LICENSE +0 -0
  24. {multipers-2.0.3 → multipers-2.0.4}/MANIFEST.in +0 -0
  25. {multipers-2.0.3 → multipers-2.0.4}/README.md +0 -0
  26. {multipers-2.0.3 → multipers-2.0.4}/multipers/__init__.py +0 -0
  27. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/MOL2.py +0 -0
  28. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/UCR.py +0 -0
  29. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/__init__.py +0 -0
  30. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/graphs.py +0 -0
  31. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/immuno_regions.py +0 -0
  32. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/minimal_presentation_to_st_bf.py +0 -0
  33. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/pytorch2simplextree.py +0 -0
  34. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/shape3d.py +0 -0
  35. {multipers-2.0.3 → multipers-2.0.4}/multipers/data/synthetic.py +0 -0
  36. {multipers-2.0.3 → multipers-2.0.4}/multipers/distances.py +0 -0
  37. {multipers-2.0.3 → multipers-2.0.4}/multipers/euler_characteristic.pyx +0 -0
  38. {multipers-2.0.3 → multipers-2.0.4}/multipers/filtration_conversions.pxd +0 -0
  39. {multipers-2.0.3 → multipers-2.0.4}/multipers/filtrations.pxd +0 -0
  40. {multipers-2.0.3 → multipers-2.0.4}/multipers/function_rips.pyx +0 -0
  41. {multipers-2.0.3 → multipers-2.0.4}/multipers/grids.pyx +0 -0
  42. {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/Persistence_slices_interface.h +0 -0
  43. {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/Simplex_tree_multi_interface.h +0 -0
  44. {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Box.h +0 -0
  45. {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Finitely_critical_filtrations.h +0 -0
  46. {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Line.h +0 -0
  47. {multipers-2.0.3 → multipers-2.0.4}/multipers/hilbert_function.pyi +0 -0
  48. {multipers-2.0.3 → multipers-2.0.4}/multipers/hilbert_function.pyx +0 -0
  49. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/__init__.py +0 -0
  50. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/accuracies.py +0 -0
  51. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/convolutions.py +0 -0
  52. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/invariants_with_persistable.py +0 -0
  53. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/kernels.py +0 -0
  54. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/mma.py +0 -0
  55. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/one.py +0 -0
  56. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/point_clouds.py +0 -0
  57. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/signed_betti.py +0 -0
  58. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/signed_measures.py +0 -0
  59. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/sliced_wasserstein.py +0 -0
  60. {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/tools.py +0 -0
  61. {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.pxd +0 -0
  62. {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.pyx +0 -0
  63. {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/euler_characteristic.h +0 -0
  64. {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/function_rips.h +0 -0
  65. {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/hilbert_function.h +0 -0
  66. {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/rank_invariant.h +0 -0
  67. {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_edge_collapse.py +0 -0
  68. {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation/approximation.h +0 -0
  69. {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation/utilities.h +0 -0
  70. {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation.pyx +0 -0
  71. {multipers-2.0.3 → multipers-2.0.4}/multipers/pickle.py +0 -0
  72. {multipers-2.0.3 → multipers-2.0.4}/multipers/plots.py +0 -0
  73. {multipers-2.0.3 → multipers-2.0.4}/multipers/point_measure_integration.pyx +0 -0
  74. {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.pxd +0 -0
  75. {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.pxd +0 -0
  76. {multipers-2.0.3 → multipers-2.0.4}/multipers/tensor.pxd +0 -0
  77. {multipers-2.0.3 → multipers-2.0.4}/multipers/test.pyx +0 -0
  78. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/old_test_rank_invariant.py +0 -0
  79. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_diff_helper.py +0 -0
  80. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_hilbert_function.py +0 -0
  81. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_mma.py +0 -0
  82. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_point_clouds.py +0 -0
  83. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_python-cpp_conversion.py +0 -0
  84. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_signed_betti.py +0 -0
  85. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_simplextreemulti.py +0 -0
  86. {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_slicer.py +0 -0
  87. {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/__init__.py +0 -0
  88. {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/diff_grids.py +0 -0
  89. {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/rips_density.py +0 -0
  90. {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/dependency_links.txt +0 -0
  91. {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/requires.txt +0 -0
  92. {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/top_level.txt +0 -0
  93. {multipers-2.0.3 → multipers-2.0.4}/pyproject.toml +0 -0
  94. {multipers-2.0.3 → multipers-2.0.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: multipers
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: Scikit-style Multiparameter persistence toolkit
5
5
  Home-page: https://github.com/DavidLapous/multipers
6
6
  Author: David Loiseaux
@@ -2,20 +2,23 @@ from typing import Iterable, Optional, Union
2
2
 
3
3
  import numpy as np
4
4
 
5
+ import multipers as mp
5
6
  from multipers.grids import compute_grid, sms_in_grid
6
7
  from multipers.plots import plot_signed_measures
7
8
  from multipers.point_measure_integration import clean_sms, zero_out_sms
8
9
  from multipers.rank_invariant import rank_from_slicer
9
- from multipers.simplex_tree_multi import (SimplexTreeMulti_type,
10
- _available_strategies,
11
- is_simplextree_multi)
10
+ from multipers.simplex_tree_multi import (
11
+ SimplexTreeMulti_type,
12
+ _available_strategies,
13
+ is_simplextree_multi,
14
+ )
12
15
  from multipers.slicer import Slicer_type, is_slicer
13
16
 
14
17
 
15
18
  def signed_measure(
16
19
  filtered_complex: Union[SimplexTreeMulti_type, Slicer_type],
17
20
  degree: Optional[int] = None,
18
- degrees: Iterable[int | None] = [None],
21
+ degrees: Iterable[int | None] = [],
19
22
  mass_default=None,
20
23
  grid_strategy: _available_strategies = "exact",
21
24
  invariant: Optional[str] = None,
@@ -29,7 +32,7 @@ def signed_measure(
29
32
  coordinate_measure: bool = False,
30
33
  num_collapses: int = 0,
31
34
  clean: Optional[bool] = None,
32
- vineyard:bool=False,
35
+ vineyard: bool = False,
33
36
  **infer_grid_kwargs,
34
37
  ) -> list[tuple[np.ndarray, np.ndarray]]:
35
38
  """
@@ -50,7 +53,7 @@ def signed_measure(
50
53
  Defaults to #cpu, but when doing parallel computations of signed measures, we recommend setting this to 1.
51
54
  - verbose:bool, prints c++ logs.
52
55
  - expand_collapse: when the input is a simplextree, only expands the complex when computing 1-dimensional slices. Meant to reduce memory footprint at some computational expense.
53
- - backend:str when the input is a simplextree, reduce first the filtered complex using an external library
56
+ - backend:str reduces first the filtered complex using an external library,
54
57
  see ``backend`` in :func:`multipers.io.reduce_complex`.
55
58
  - grid_conversion: If given, re-evaluates the final signed measure in this grid.
56
59
  - coordinate_measure: bool, if True, compute the signed measure as a coordinates given in grid_conversion.
@@ -64,13 +67,13 @@ def signed_measure(
64
67
  with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
65
68
  """
66
69
 
67
- if len(degrees) == 1 and degrees[0] is None and degree is not None:
68
- degrees = [degree]
70
+ if degree is not None or len(degrees) == 0:
71
+ degrees = list(degrees) + [degree]
69
72
  if None in degrees:
70
- assert len(degrees) == 1
73
+ assert (
74
+ len(degrees) == 1
75
+ ), f"Can only compute one invariant at the time. Got {degrees=}, {invariant=}."
71
76
  invariant = "euler"
72
- if len(degrees) == 0:
73
- return []
74
77
  if clean is None:
75
78
  clean = True if None in degrees else False
76
79
 
@@ -96,20 +99,25 @@ def signed_measure(
96
99
 
97
100
  if mass_default is None:
98
101
  mass_default = mass_default
99
- elif mass_default == "inf":
100
- mass_default = np.array([np.inf] * filtered_complex.num_parameters)
101
- elif mass_default == "auto": # this will not work with torch, but we don't want to autodiff this anyway
102
- mass_default = np.array(
103
- [1.1 * np.max(f) - 0.1 * np.min(f) for f in grid_conversion]
104
- )
102
+ elif isinstance(mass_default, str):
103
+ if mass_default == "auto":
104
+ mass_default = np.array(
105
+ [1.1 * np.max(f) - 0.1 * np.min(f) for f in grid_conversion]
106
+ )
107
+ elif mass_default == "inf":
108
+ mass_default = np.array([np.inf] * filtered_complex.num_parameters)
109
+ else:
110
+ raise NotImplementedError
105
111
  else:
106
112
  mass_default = np.asarray(mass_default)
107
113
  assert (
108
114
  mass_default.ndim == 1
109
115
  and mass_default.shape[0] == filtered_complex.num_parameters
110
116
  )
111
-
112
- INPUT_ARGS = locals()
117
+
118
+ # INPUT_ARGS = locals()
119
+ # INPUT_ARGS.pop("filtered_complex")
120
+
113
121
  if not filtered_complex.is_squeezed:
114
122
  filtered_complex_ = filtered_complex.grid_squeeze(
115
123
  grid_conversion, coordinates=True
@@ -122,88 +130,88 @@ def signed_measure(
122
130
  grid_conversion
123
131
  ), f"Number of parameter do not coincide. Got (grid_conversion) {len(grid_conversion)} and (filtered complex) {num_parameters}."
124
132
 
133
+ if is_simplextree_multi(filtered_complex_):
134
+ if num_collapses != 0:
135
+ filtered_complex_.collapse_edges(num_collapses)
136
+ if backend is not None:
137
+ filtered_complex_ = mp.Slicer(filtered_complex_, vineyard=vineyard)
138
+
125
139
  fix_mass_default = mass_default is not None
126
140
  if is_slicer(filtered_complex_):
127
- if backend is not None:
141
+ if backend is not None and not filtered_complex_.is_minpres:
128
142
  from multipers.slicer import minimal_presentation
143
+
129
144
  assert (
130
145
  invariant != "euler"
131
146
  ), "Euler Characteristic cannot be speed up by a backend"
132
147
  # This returns a list of reduced complexes
133
- reduced_complex = minimal_presentation(filtered_complex_, degrees=degrees, backend=backend, vineyard = vineyard)
134
- if invariant in ("rank", "rank_invariant"):
148
+ reduced_complex = minimal_presentation(
149
+ filtered_complex_,
150
+ degrees=degrees,
151
+ backend=backend,
152
+ vineyard=vineyard,
153
+ verbose=verbose,
154
+ )
155
+ if "rank" in invariant:
135
156
  sms = [
136
157
  rank_from_slicer(
137
158
  s,
138
159
  degrees=[1],
139
160
  n_jobs=n_jobs,
140
161
  grid_shape=tuple(len(g) for g in grid_conversion),
141
- plot=plot,
142
- )
162
+ zero_pad=fix_mass_default,
163
+ )[0]
143
164
  for s, d in zip(reduced_complex, degrees)
144
165
  ]
166
+ fix_mass_default = False
145
167
  else:
146
- sms = [
147
- _signed_measure_from_slicer(s)[0]
148
- for s in reduced_complex
149
- ]
150
- else: # No backend
151
- if invariant in ("rank", "rank_invariant"): # TODO Hilbert from slicer
168
+ sms = [_signed_measure_from_slicer(s)[0] for s in reduced_complex]
169
+ else: # No backend
170
+ if "rank" in invariant: # TODO Hilbert from slicer
152
171
  degrees = np.asarray(degrees, dtype=int)
153
- return rank_from_slicer(
172
+ sms = rank_from_slicer(
154
173
  filtered_complex_,
155
174
  degrees=degrees,
156
175
  n_jobs=n_jobs,
176
+ zero_pad=fix_mass_default,
157
177
  grid_shape=tuple(len(g) for g in grid_conversion),
158
- plot=plot,
159
178
  )
160
- elif invariant is None or "euler" in invariant:
179
+ fix_mass_default = False
180
+ elif filtered_complex_.is_minpres:
181
+ sms = _signed_measure_from_slicer(
182
+ filtered_complex_,
183
+ )
184
+ elif (invariant is None or "euler" in invariant) and (
185
+ len(degrees) == 1 and degrees[0] is None
186
+ ):
161
187
  sms = _signed_measure_from_slicer(
162
188
  filtered_complex_,
163
189
  )
164
190
  else:
165
- if filtered_complex_.is_minpres:
166
- assert len(degrees) == 1
167
- sms = _signed_measure_from_slicer(filtered_complex_)
191
+ from multipers.slicer import minimal_presentation
168
192
 
169
- else:
170
- from multipers.slicer import minimal_presentation
171
- reduced_complex = minimal_presentation(filtered_complex_, degrees=degrees, backend=backend, vineyard=vineyard)
172
- sms = [_signed_measure_from_slicer(s)[0]
173
- for s in reduced_complex
174
- ]
175
-
193
+ backend = "mpfree" ## TODO : make a non-mpfree backend
194
+ reduced_complex = minimal_presentation(
195
+ filtered_complex_,
196
+ degrees=degrees,
197
+ backend=backend,
198
+ vineyard=vineyard,
199
+ )
200
+ sms = [_signed_measure_from_slicer(s)[0] for s in reduced_complex]
176
201
 
177
202
  elif is_simplextree_multi(filtered_complex_):
178
- if num_collapses != 0:
179
- filtered_complex_.collapse_edges(num_collapses)
180
- if backend is not None:
181
- from multipers.slicer import minimal_presentation
182
- reduced_complex = minimal_presentation(filtered_complex_, degrees=degrees, backend=backend, vineyard=vineyard)
183
- # this is a list of slicer -> need to go back
184
- INPUT_ARGS.pop('filtered_complex')
185
- INPUT_ARGS.pop('degrees')
186
- INPUT_ARGS.pop('degree')
187
- INPUT_ARGS.pop('backend')
188
- plot = INPUT_ARGS.pop('plot') ## plot has to be dealt with later
189
- output = [_signed_measure_from_slicer(s, degree=d, **INPUT_ARGS)[0] for s,d in zip(reduced_complex, degrees)]
190
- if plot:
191
- plot_signed_measures(output)
192
- return output
193
203
  ## we still have a simplextree here
194
204
  if invariant in ["rank_invariant", "rank"]:
195
205
  assert (
196
- filtered_complex.num_parameters == 2
206
+ num_parameters == 2
197
207
  ), "Rank invariant only implemented for 2-parameter modules."
198
208
  assert not coordinate_measure, "Not implemented"
199
- from multipers.simplex_tree_multi import \
200
- _rank_signed_measure as smri
209
+ from multipers.simplex_tree_multi import _rank_signed_measure as smri
201
210
 
202
211
  sms = smri(
203
212
  filtered_complex_,
204
213
  mass_default=mass_default,
205
214
  degrees=degrees,
206
- plot=plot,
207
215
  expand_collapse=expand_collapse,
208
216
  )
209
217
  fix_mass_default = False
@@ -228,8 +236,9 @@ def signed_measure(
228
236
  "hilbert",
229
237
  "hilbert_function",
230
238
  ], "Found homological degrees for euler computation."
231
- from multipers.simplex_tree_multi import \
232
- _hilbert_signed_measure as hilbert_signed_measure
239
+ from multipers.simplex_tree_multi import (
240
+ _hilbert_signed_measure as hilbert_signed_measure,
241
+ )
233
242
 
234
243
  sms = hilbert_signed_measure(
235
244
  filtered_complex_,
@@ -246,7 +255,12 @@ def signed_measure(
246
255
  if clean:
247
256
  sms = clean_sms(sms)
248
257
  if grid_conversion is not None and not coordinate_measure:
249
- sms = sms_in_grid(sms, grid_conversion=grid_conversion, mass_default=mass_default, num_parameters=num_parameters)
258
+ sms = sms_in_grid(
259
+ sms,
260
+ grid_conversion=grid_conversion,
261
+ mass_default=mass_default,
262
+ num_parameters=num_parameters,
263
+ )
250
264
 
251
265
  if fix_mass_default:
252
266
  # TODO : some methods need to use this, this could be optimized
@@ -139,6 +139,7 @@ def Slicer(
139
139
  )
140
140
  if st.is_squeezed:
141
141
  slicer.filtration_grid = st.filtration_grid
142
+ slicer.minpres_degree = st.minpres_degree
142
143
  elif is_simplextree_multi(st) and backend == "graph":
143
144
  slicer = _slicer_from_simplextree(st, backend, vineyard)
144
145
  if st.is_squeezed: