multipers 2.3.3b6__cp310-cp310-win_amd64.whl → 2.3.4__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.

@@ -9,12 +9,107 @@ from sklearn.base import BaseEstimator, TransformerMixin
9
9
  from tqdm import tqdm
10
10
 
11
11
  import multipers as mp
12
- from multipers.array_api import api_from_tensor
12
+ from multipers.array_api import api_from_tensor, api_from_tensors
13
13
  from multipers.filtrations.density import available_kernels, convolution_signed_measures
14
- from multipers.grids import compute_grid
14
+ from multipers.grids import compute_grid, todense
15
15
  from multipers.point_measure import rank_decomposition_by_rectangles, signed_betti
16
16
 
17
17
 
18
+ def batch_signed_measure_convolutions(
19
+ signed_measures, # array of shape (num_data,num_pts,D)
20
+ x, # array of shape (num_x, D) or (num_data, num_x, D)
21
+ bandwidth, # either float or matrix if multivariate kernel
22
+ kernel: available_kernels,
23
+ api=None,
24
+ ):
25
+ """
26
+ Input
27
+ -----
28
+ - signed_measures: unragged, of shape (num_data, num_pts, D+1)
29
+ where last coord is weights, (0 for dummy points)
30
+ - x : the points to convolve (num_x,D)
31
+ - bandwidth : the bandwidths or covariance matrix inverse or ... of the kernel
32
+ - kernel : "gaussian", "multivariate_gaussian", "exponential", or Callable (x_i, y_i, bandwidth)->float
33
+
34
+ Output
35
+ ------
36
+ Array of shape (num_convolutions, (num_axis), num_data,
37
+ Array of shape (num_convolutions, (num_axis), num_data, max_x_size)
38
+ """
39
+ from multipers.filtrations.density import _kernel
40
+
41
+ if api is None:
42
+ api = api_from_tensors(signed_measures, x)
43
+ if signed_measures.ndim == 2:
44
+ signed_measures = signed_measures[None, :, :]
45
+ sms = signed_measures[..., :-1]
46
+ weights = signed_measures[..., -1]
47
+ _sms = api.LazyTensor(api.ascontiguous(sms[..., None, :]))
48
+ _x = api.ascontiguous(x[..., None, :, :])
49
+
50
+ sms_kernel = _kernel(kernel)(_sms, _x, bandwidth)
51
+ out = (sms_kernel * api.ascontiguous(weights[..., None, None])).sum(
52
+ signed_measures.ndim - 2
53
+ )
54
+ assert out.shape[-1] == 1, "Pykeops bug fixed, TODO : refix this "
55
+ out = out[..., 0] ## pykeops bug + ensures its a tensor
56
+ # assert out.shape == (x.shape[0], x.shape[1]), f"{x.shape=}, {out.shape=}"
57
+ return out
58
+
59
+
60
+ def sm2deep(signed_measure, api=None):
61
+ if api is None:
62
+ api = api_from_tensor(signed_measure[0])
63
+ dirac_positions, dirac_signs = signed_measure
64
+ dtype = dirac_positions.dtype
65
+ new_shape = list(dirac_positions.shape)
66
+ new_shape[1] += 1
67
+ c = api.empty(new_shape, dtype=dtype)
68
+ c[:, :-1] = dirac_positions
69
+ c[:, -1] = api.astensor(dirac_signs)
70
+ return c
71
+
72
+
73
+ def deep_unrag(sms, api=None):
74
+ if api is None:
75
+ api = api_from_tensor(sms[0][0])
76
+ num_sm = len(sms)
77
+ if num_sm == 0:
78
+ return api.tensor([])
79
+ first = sms[0][0]
80
+ num_parameters = first.shape[1]
81
+ dtype = first.dtype
82
+ deep_sms = tuple(sm2deep(sm, api=api) for sm in sms)
83
+ max_num_pts = np.max([sm[0].shape[0] for sm in sms])
84
+ unragged_sms = api.zeros((num_sm, max_num_pts, num_parameters + 1), dtype=dtype)
85
+
86
+ for data in range(num_sm):
87
+ sm = deep_sms[data]
88
+ a, b = sm.shape
89
+ unragged_sms[data, :a, :b] = sm
90
+ return unragged_sms
91
+
92
+
93
+ def sm_convolution(
94
+ sms,
95
+ grid,
96
+ bandwidth,
97
+ kernel: available_kernels = "gaussian",
98
+ plot: bool = False,
99
+ **plt_kwargs,
100
+ ):
101
+ dense_grid = todense(grid)
102
+ api = api_from_tensors(sms[0][0], dense_grid)
103
+ sms = deep_unrag(sms, api=api)
104
+ convs = batch_signed_measure_convolutions(
105
+ sms, dense_grid, bandwidth, kernel, api=api
106
+ ).reshape(sms.shape[0], *(len(g) for g in grid))
107
+ if plot:
108
+ from multipers.plots import plot_surfaces
109
+ plot_surfaces((grid, convs), **plt_kwargs)
110
+ return convs
111
+
112
+
18
113
  class FilteredComplex2SignedMeasure(BaseEstimator, TransformerMixin):
19
114
  """
20
115
  Input
@@ -547,27 +642,6 @@ def rescale_sparse_signed_measure(
547
642
  return out
548
643
 
549
644
 
550
- def sm2deep(signed_measure):
551
- dirac_positions, dirac_signs = signed_measure
552
- dtype = dirac_positions.dtype
553
- new_shape = list(dirac_positions.shape)
554
- new_shape[1] += 1
555
- if isinstance(dirac_positions, np.ndarray):
556
- c = np.empty(new_shape, dtype=dtype)
557
- c[:, :-1] = dirac_positions
558
- c[:, -1] = dirac_signs
559
-
560
- else:
561
- import torch
562
-
563
- c = torch.empty(new_shape, dtype=dtype)
564
- c[:, :-1] = dirac_positions
565
- if isinstance(dirac_signs, np.ndarray):
566
- dirac_signs = torch.from_numpy(dirac_signs)
567
- c[:, -1] = dirac_signs
568
- return c
569
-
570
-
571
645
  class SignedMeasureFormatter(BaseEstimator, TransformerMixin):
572
646
  """
573
647
  Input
@@ -759,7 +833,9 @@ class SignedMeasureFormatter(BaseEstimator, TransformerMixin):
759
833
  self._filtrations_bounds.append(filtration_bounds)
760
834
  self._normalization_factors.append(normalization_factors)
761
835
  self._filtrations_bounds = self._backend.astensor(self._filtrations_bounds)
762
- self._normalization_factors = self._backend.astensor(self._normalization_factors)
836
+ self._normalization_factors = self._backend.astensor(
837
+ self._normalization_factors
838
+ )
763
839
  # else:
764
840
  # (
765
841
  # self._filtrations_bounds,
@@ -784,9 +860,11 @@ class SignedMeasureFormatter(BaseEstimator, TransformerMixin):
784
860
  ]
785
861
  # axis, filtration_values
786
862
  filtration_values = [
787
- self._backend.astensor(compute_grid(
788
- f_ax.T, resolution=self.resolution, strategy=self.grid_strategy
789
- ))
863
+ self._backend.astensor(
864
+ compute_grid(
865
+ f_ax.T, resolution=self.resolution, strategy=self.grid_strategy
866
+ )
867
+ )
790
868
  for f_ax in filtration_values
791
869
  ]
792
870
  self._infered_grids = filtration_values
@@ -751,7 +751,7 @@ cdef class PyModule_f64:
751
751
  axs = [plt.gca()]
752
752
  for image, degree, i in zip(image_vector, degrees, range(num_degrees)):
753
753
  ax = axs[i]
754
- temp = multipers.plots.plot_surface(grid, image.T, ax=ax)
754
+ temp = multipers.plots.plot_surface(grid, image, ax=ax)
755
755
  plt.colorbar(temp, ax = ax)
756
756
  if degree < 0 :
757
757
  ax.set_title(rf"$H_{i}$ $2$-persistence image")
@@ -1712,7 +1712,7 @@ cdef class PyModule_f32:
1712
1712
  axs = [plt.gca()]
1713
1713
  for image, degree, i in zip(image_vector, degrees, range(num_degrees)):
1714
1714
  ax = axs[i]
1715
- temp = multipers.plots.plot_surface(grid, image.T, ax=ax)
1715
+ temp = multipers.plots.plot_surface(grid, image, ax=ax)
1716
1716
  plt.colorbar(temp, ax = ax)
1717
1717
  if degree < 0 :
1718
1718
  ax.set_title(rf"$H_{i}$ $2$-persistence image")
@@ -773,7 +773,7 @@ cdef class PyModule_{{SHORT}}:
773
773
  axs = [plt.gca()]
774
774
  for image, degree, i in zip(image_vector, degrees, range(num_degrees)):
775
775
  ax = axs[i]
776
- temp = multipers.plots.plot_surface(grid, image.T, ax=ax)
776
+ temp = multipers.plots.plot_surface(grid, image, ax=ax)
777
777
  plt.colorbar(temp, ax = ax)
778
778
  if degree < 0 :
779
779
  ax.set_title(rf"$H_{i}$ $2$-persistence image")
multipers/plots.py CHANGED
@@ -81,7 +81,8 @@ def _plot_signed_measure_4(
81
81
  **plt_kwargs, # ignored ftm
82
82
  ):
83
83
  # compute the maximal rectangle area
84
- pts = np.clip(pts, a_min=-np.inf, a_max=np.array((*threshold, *threshold))[None, :])
84
+ pts = np.clip(pts, a_min=-np.inf,
85
+ a_max=np.array((*threshold, *threshold))[None, :])
85
86
  alpha_rescaling = 0
86
87
  for rectangle, weight in zip(pts, weights):
87
88
  if rectangle[2] >= x_smoothing * rectangle[0]:
@@ -170,7 +171,8 @@ def plot_signed_measures(signed_measures, threshold=None, size=4):
170
171
  nrows=1, ncols=num_degrees, figsize=(num_degrees * size, size)
171
172
  )
172
173
  for ax, signed_measure in zip(axes, signed_measures):
173
- plot_signed_measure(signed_measure=signed_measure, ax=ax, threshold=threshold)
174
+ plot_signed_measure(signed_measure=signed_measure,
175
+ ax=ax, threshold=threshold)
174
176
  plt.tight_layout()
175
177
 
176
178
 
@@ -200,13 +202,17 @@ def plot_surface(
200
202
  cmap = matplotlib.colormaps["gray_r"]
201
203
  else:
202
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]
203
208
  if discrete_surface:
204
209
  if has_negative_values:
205
210
  bounds = np.arange(-5, 6, 1, dtype=int)
206
211
  else:
207
212
  bounds = np.arange(0, 11, 1, dtype=int)
208
213
  norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N, extend="max")
209
- im = ax.pcolormesh(grid[0], grid[1], hf.T, cmap=cmap, norm=norm, **plt_args)
214
+ im = ax.pcolormesh(grid[0], grid[1], hf.T, cmap=cmap,
215
+ norm=norm, shading="flat", **plt_args)
210
216
  cbar = fig.colorbar(
211
217
  matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm),
212
218
  spacing="proportional",
@@ -216,10 +222,12 @@ def plot_surface(
216
222
  return im
217
223
 
218
224
  if contour:
219
- levels = plt_args.pop("levels", 20)
220
- im = ax.contourf(grid[0], grid[1], hf.T, cmap=cmap, levels=levels, **plt_args)
225
+ levels = plt_args.pop("levels", 50)
226
+ im = ax.contourf(grid[0], grid[1], hf.T,
227
+ cmap=cmap, levels=levels, **plt_args)
221
228
  else:
222
- im = ax.pcolormesh(grid[0], grid[1], hf.T, cmap=cmap, **plt_args)
229
+ im = ax.pcolormesh(grid[0], grid[1], hf.T,
230
+ cmap=cmap, shading="flat", **plt_args)
223
231
  return im
224
232
 
225
233
 
@@ -314,25 +322,30 @@ def plot2d_PyModule(
314
322
  trivial_summand = False
315
323
  if shapely:
316
324
  list_of_rect.append(
317
- _rectangle_box(birth[0], birth[1], death[0], death[1])
325
+ _rectangle_box(
326
+ birth[0], birth[1], death[0], death[1])
318
327
  )
319
328
  else:
320
329
  list_of_rect.append(
321
- _rectangle(birth, death, cmap(i / n_summands), alpha)
330
+ _rectangle(birth, death, cmap(
331
+ i / n_summands), alpha)
322
332
  )
323
333
  if not (trivial_summand):
324
334
  if separated:
325
335
  fig, ax = plt.subplots()
326
- ax.set(xlim=[box[0][0], box[1][0]], ylim=[box[0][1], box[1][1]])
336
+ ax.set(xlim=[box[0][0], box[1][0]],
337
+ ylim=[box[0][1], box[1][1]])
327
338
  if shapely:
328
339
  summand_shape = union_all(list_of_rect)
329
340
  if type(summand_shape) is _Polygon:
330
341
  xs, ys = summand_shape.exterior.xy
331
- ax.fill(xs, ys, alpha=alpha, fc=cmap(i / n_summands), ec="None")
342
+ ax.fill(xs, ys, alpha=alpha, fc=cmap(
343
+ i / n_summands), ec="None")
332
344
  else:
333
345
  for polygon in summand_shape.geoms:
334
346
  xs, ys = polygon.exterior.xy
335
- ax.fill(xs, ys, alpha=alpha, fc=cmap(i / n_summands), ec="None")
347
+ ax.fill(xs, ys, alpha=alpha, fc=cmap(
348
+ i / n_summands), ec="None")
336
349
  else:
337
350
  for rectangle in list_of_rect:
338
351
  ax.add_patch(rectangle)
@@ -396,7 +409,8 @@ def plot_simplicial_complex(
396
409
  if len(s) == 2: # simplexe = segment
397
410
  xx = np.array([pts[a, 0] for a in s])
398
411
  yy = np.array([pts[a, 1] for a in s])
399
- plt.plot(xx, yy, c=color(density), alpha=1, zorder=10 * density, lw=1.5)
412
+ plt.plot(xx, yy, c=color(density), alpha=1,
413
+ zorder=10 * density, lw=1.5)
400
414
  if len(s) == 3: # simplexe = triangle
401
415
  xx = np.array([pts[a, 0] for a in s])
402
416
  yy = np.array([pts[a, 1] for a in s])
Binary file
@@ -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
 
@@ -625,6 +625,41 @@ cdef class SimplexTreeMulti_KFi32:
625
625
  """
626
626
  return self.get_ptr().prune_above_dimension(dimension)
627
627
 
628
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFi32:
629
+ """Expands the simplex tree containing only its one skeleton
630
+ until dimension max_dim.
631
+
632
+ The expanded simplicial complex until dimension :math:`d`
633
+ attached to a graph :math:`G` is the maximal simplicial complex of
634
+ dimension at most :math:`d` admitting the graph :math:`G` as
635
+ :math:`1`-skeleton.
636
+ The filtration value assigned to a simplex is the maximal filtration
637
+ value of one of its edges.
638
+
639
+ The simplex tree must contain no simplex of dimension bigger than
640
+ 1 when calling the method.
641
+
642
+ :param max_dim: The maximal dimension.
643
+ :type max_dim: int
644
+ """
645
+ with nogil:
646
+ self.get_ptr().expansion(max_dim)
647
+ # This is a fix for multipersistence. FIXME expansion in c++
648
+ self.get_ptr().make_filtration_non_decreasing()
649
+ return self
650
+
651
+ def make_filtration_non_decreasing(self)->bool:
652
+ """This function ensures that each simplex has a higher filtration
653
+ value than its faces by increasing the filtration values.
654
+
655
+ :returns: True if any filtration value was modified,
656
+ False if the filtration was already non-decreasing.
657
+ :rtype: bool
658
+ """
659
+ cdef bool out
660
+ with nogil:
661
+ out = self.get_ptr().make_filtration_non_decreasing()
662
+ return out
628
663
 
629
664
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFi32:
630
665
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -3217,6 +3252,41 @@ cdef class SimplexTreeMulti_KFi64:
3217
3252
  """
3218
3253
  return self.get_ptr().prune_above_dimension(dimension)
3219
3254
 
3255
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFi64:
3256
+ """Expands the simplex tree containing only its one skeleton
3257
+ until dimension max_dim.
3258
+
3259
+ The expanded simplicial complex until dimension :math:`d`
3260
+ attached to a graph :math:`G` is the maximal simplicial complex of
3261
+ dimension at most :math:`d` admitting the graph :math:`G` as
3262
+ :math:`1`-skeleton.
3263
+ The filtration value assigned to a simplex is the maximal filtration
3264
+ value of one of its edges.
3265
+
3266
+ The simplex tree must contain no simplex of dimension bigger than
3267
+ 1 when calling the method.
3268
+
3269
+ :param max_dim: The maximal dimension.
3270
+ :type max_dim: int
3271
+ """
3272
+ with nogil:
3273
+ self.get_ptr().expansion(max_dim)
3274
+ # This is a fix for multipersistence. FIXME expansion in c++
3275
+ self.get_ptr().make_filtration_non_decreasing()
3276
+ return self
3277
+
3278
+ def make_filtration_non_decreasing(self)->bool:
3279
+ """This function ensures that each simplex has a higher filtration
3280
+ value than its faces by increasing the filtration values.
3281
+
3282
+ :returns: True if any filtration value was modified,
3283
+ False if the filtration was already non-decreasing.
3284
+ :rtype: bool
3285
+ """
3286
+ cdef bool out
3287
+ with nogil:
3288
+ out = self.get_ptr().make_filtration_non_decreasing()
3289
+ return out
3220
3290
 
3221
3291
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFi64:
3222
3292
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -5809,6 +5879,41 @@ cdef class SimplexTreeMulti_KFf32:
5809
5879
  """
5810
5880
  return self.get_ptr().prune_above_dimension(dimension)
5811
5881
 
5882
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFf32:
5883
+ """Expands the simplex tree containing only its one skeleton
5884
+ until dimension max_dim.
5885
+
5886
+ The expanded simplicial complex until dimension :math:`d`
5887
+ attached to a graph :math:`G` is the maximal simplicial complex of
5888
+ dimension at most :math:`d` admitting the graph :math:`G` as
5889
+ :math:`1`-skeleton.
5890
+ The filtration value assigned to a simplex is the maximal filtration
5891
+ value of one of its edges.
5892
+
5893
+ The simplex tree must contain no simplex of dimension bigger than
5894
+ 1 when calling the method.
5895
+
5896
+ :param max_dim: The maximal dimension.
5897
+ :type max_dim: int
5898
+ """
5899
+ with nogil:
5900
+ self.get_ptr().expansion(max_dim)
5901
+ # This is a fix for multipersistence. FIXME expansion in c++
5902
+ self.get_ptr().make_filtration_non_decreasing()
5903
+ return self
5904
+
5905
+ def make_filtration_non_decreasing(self)->bool:
5906
+ """This function ensures that each simplex has a higher filtration
5907
+ value than its faces by increasing the filtration values.
5908
+
5909
+ :returns: True if any filtration value was modified,
5910
+ False if the filtration was already non-decreasing.
5911
+ :rtype: bool
5912
+ """
5913
+ cdef bool out
5914
+ with nogil:
5915
+ out = self.get_ptr().make_filtration_non_decreasing()
5916
+ return out
5812
5917
 
5813
5918
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFf32:
5814
5919
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -8401,6 +8506,41 @@ cdef class SimplexTreeMulti_KFf64:
8401
8506
  """
8402
8507
  return self.get_ptr().prune_above_dimension(dimension)
8403
8508
 
8509
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFf64:
8510
+ """Expands the simplex tree containing only its one skeleton
8511
+ until dimension max_dim.
8512
+
8513
+ The expanded simplicial complex until dimension :math:`d`
8514
+ attached to a graph :math:`G` is the maximal simplicial complex of
8515
+ dimension at most :math:`d` admitting the graph :math:`G` as
8516
+ :math:`1`-skeleton.
8517
+ The filtration value assigned to a simplex is the maximal filtration
8518
+ value of one of its edges.
8519
+
8520
+ The simplex tree must contain no simplex of dimension bigger than
8521
+ 1 when calling the method.
8522
+
8523
+ :param max_dim: The maximal dimension.
8524
+ :type max_dim: int
8525
+ """
8526
+ with nogil:
8527
+ self.get_ptr().expansion(max_dim)
8528
+ # This is a fix for multipersistence. FIXME expansion in c++
8529
+ self.get_ptr().make_filtration_non_decreasing()
8530
+ return self
8531
+
8532
+ def make_filtration_non_decreasing(self)->bool:
8533
+ """This function ensures that each simplex has a higher filtration
8534
+ value than its faces by increasing the filtration values.
8535
+
8536
+ :returns: True if any filtration value was modified,
8537
+ False if the filtration was already non-decreasing.
8538
+ :rtype: bool
8539
+ """
8540
+ cdef bool out
8541
+ with nogil:
8542
+ out = self.get_ptr().make_filtration_non_decreasing()
8543
+ return out
8404
8544
 
8405
8545
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFf64:
8406
8546
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -869,7 +869,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
869
869
  """
870
870
  return self.get_ptr().prune_above_dimension(dimension)
871
871
 
872
- {{if not is_kcritical}}
873
872
  def expansion(self, int max_dim)->SimplexTreeMulti_{{FSHORT}}:
874
873
  """Expands the simplex tree containing only its one skeleton
875
874
  until dimension max_dim.
@@ -905,7 +904,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
905
904
  with nogil:
906
905
  out = self.get_ptr().make_filtration_non_decreasing()
907
906
  return out
908
- {{endif}}
909
907
 
910
908
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_{{FSHORT}}:
911
909
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
Binary file
multipers/slicer.pyx CHANGED
@@ -19914,7 +19914,7 @@ def _from_bitmapi64(image, **slicer_kwargs):
19914
19914
  # print(f"F = {np.asarray(F[i])}")
19915
19915
  slicer = _Slicer(gen_maps, gen_dims, filtration_values)
19916
19916
  return slicer
19917
- def _from_bitmapf64(image, **slicer_kwargs):
19917
+ def _from_bitmapf32(image, **slicer_kwargs):
19918
19918
  from multipers import Slicer
19919
19919
  dtype = slicer_kwargs.get("dtype", image.dtype)
19920
19920
  slicer_kwargs["dtype"] = dtype
@@ -19932,9 +19932,9 @@ def _from_bitmapf64(image, **slicer_kwargs):
19932
19932
  cdef cset[unsigned int] vertices
19933
19933
 
19934
19934
  cdef unsigned int num_gens = gen_dims.size()
19935
- filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.float64) - _Slicer._inf_value()
19936
- cdef double[:,:] F = filtration_values
19937
- cdef double[:,:] c_img = image.reshape(-1,num_parameters)
19935
+ filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.float32) - _Slicer._inf_value()
19936
+ cdef float[:,:] F = filtration_values
19937
+ cdef float[:,:] c_img = image.reshape(-1,num_parameters)
19938
19938
  with nogil:
19939
19939
  for i in range(num_gens):
19940
19940
  # with gil:
@@ -19952,7 +19952,7 @@ def _from_bitmapf64(image, **slicer_kwargs):
19952
19952
  # print(f"F = {np.asarray(F[i])}")
19953
19953
  slicer = _Slicer(gen_maps, gen_dims, filtration_values)
19954
19954
  return slicer
19955
- def _from_bitmapf32(image, **slicer_kwargs):
19955
+ def _from_bitmapi32(image, **slicer_kwargs):
19956
19956
  from multipers import Slicer
19957
19957
  dtype = slicer_kwargs.get("dtype", image.dtype)
19958
19958
  slicer_kwargs["dtype"] = dtype
@@ -19970,9 +19970,9 @@ def _from_bitmapf32(image, **slicer_kwargs):
19970
19970
  cdef cset[unsigned int] vertices
19971
19971
 
19972
19972
  cdef unsigned int num_gens = gen_dims.size()
19973
- filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.float32) - _Slicer._inf_value()
19974
- cdef float[:,:] F = filtration_values
19975
- cdef float[:,:] c_img = image.reshape(-1,num_parameters)
19973
+ filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.int32) - _Slicer._inf_value()
19974
+ cdef int32_t[:,:] F = filtration_values
19975
+ cdef int32_t[:,:] c_img = image.reshape(-1,num_parameters)
19976
19976
  with nogil:
19977
19977
  for i in range(num_gens):
19978
19978
  # with gil:
@@ -19990,7 +19990,7 @@ def _from_bitmapf32(image, **slicer_kwargs):
19990
19990
  # print(f"F = {np.asarray(F[i])}")
19991
19991
  slicer = _Slicer(gen_maps, gen_dims, filtration_values)
19992
19992
  return slicer
19993
- def _from_bitmapi32(image, **slicer_kwargs):
19993
+ def _from_bitmapf64(image, **slicer_kwargs):
19994
19994
  from multipers import Slicer
19995
19995
  dtype = slicer_kwargs.get("dtype", image.dtype)
19996
19996
  slicer_kwargs["dtype"] = dtype
@@ -20008,9 +20008,9 @@ def _from_bitmapi32(image, **slicer_kwargs):
20008
20008
  cdef cset[unsigned int] vertices
20009
20009
 
20010
20010
  cdef unsigned int num_gens = gen_dims.size()
20011
- filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.int32) - _Slicer._inf_value()
20012
- cdef int32_t[:,:] F = filtration_values
20013
- cdef int32_t[:,:] c_img = image.reshape(-1,num_parameters)
20011
+ filtration_values = np.zeros(shape=(num_gens, num_parameters), dtype = np.float64) - _Slicer._inf_value()
20012
+ cdef double[:,:] F = filtration_values
20013
+ cdef double[:,:] c_img = image.reshape(-1,num_parameters)
20014
20014
  with nogil:
20015
20015
  for i in range(num_gens):
20016
20016
  # with gil:
@@ -20033,12 +20033,12 @@ def from_bitmap(img, **kwargs):
20033
20033
  img = np.asarray(img)
20034
20034
  if img.dtype == np.int64:
20035
20035
  return _from_bitmapi64(img, **kwargs)
20036
- if img.dtype == np.float64:
20037
- return _from_bitmapf64(img, **kwargs)
20038
20036
  if img.dtype == np.float32:
20039
20037
  return _from_bitmapf32(img, **kwargs)
20040
20038
  if img.dtype == np.int32:
20041
20039
  return _from_bitmapi32(img, **kwargs)
20040
+ if img.dtype == np.float64:
20041
+ return _from_bitmapf64(img, **kwargs)
20042
20042
  raise ValueError(f"Invalid dtype. Got {img.dtype=}, was expecting {available_dtype=}.")
20043
20043
 
20044
20044
  def from_function_delaunay(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multipers
3
- Version: 2.3.3b6
3
+ Version: 2.3.4
4
4
  Summary: Multiparameter Topological Persistence for Machine Learning
5
5
  Author-email: David Loiseaux <david.lapous@proton.me>, Hannah Schreiber <hannah.schreiber@inria.fr>
6
6
  Maintainer-email: David Loiseaux <david.lapous@proton.me>
@@ -44,7 +44,7 @@ This library aims to provide easy to use and performant strategies for applied m
44
44
  ## Compiled packages
45
45
  | Source | Version | Downloads | Platforms |
46
46
  | --- | --- | --- | --- |
47
- | [![Conda Recipe](https://img.shields.io/badge/conda-recipe-green.svg)](https://anaconda.org/conda-forge/multipers)| [![Conda Version](https://img.shields.io/conda/vn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) | [![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) |[![Conda Platforms](https://img.shields.io/conda/pn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) |
47
+ | [![Conda Recipe](https://img.shields.io/badge/conda-recipe-green.svg)](https://github.com/conda-forge/multipers-feedstock)| [![Conda Version](https://img.shields.io/conda/vn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) | [![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) |[![Conda Platforms](https://img.shields.io/conda/pn/conda-forge/multipers.svg)](https://anaconda.org/conda-forge/multipers) |
48
48
  | [![pip Recipe](https://img.shields.io/badge/pip-package-green.svg)](https:///pypi.org/project/multipers) | [![PyPI](https://img.shields.io/pypi/v/multipers?color=green)](https://pypi.org/project/multipers) | [![ pip downloads](https://static.pepy.tech/badge/multipers)](https://pepy.tech/project/multipers) | |
49
49
 
50
50