squarenet 1.3.2__tar.gz → 1.3.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.
Files changed (28) hide show
  1. {squarenet-1.3.2 → squarenet-1.3.4}/PKG-INFO +1 -1
  2. {squarenet-1.3.2 → squarenet-1.3.4}/pyproject.toml +1 -1
  3. squarenet-1.3.4/src/squarenet/__init__.py +4 -0
  4. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/artist.py +10 -1
  5. squarenet-1.3.4/src/squarenet/backends.py +67 -0
  6. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/squarenet.py +6 -11
  7. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/utils.py +0 -76
  8. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/PKG-INFO +1 -1
  9. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/SOURCES.txt +1 -0
  10. squarenet-1.3.2/src/squarenet/__init__.py +0 -4
  11. {squarenet-1.3.2 → squarenet-1.3.4}/README.md +0 -0
  12. {squarenet-1.3.2 → squarenet-1.3.4}/setup.cfg +0 -0
  13. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/core.py +0 -0
  14. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/data/__init__.py +0 -0
  15. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/neighbormap.py +0 -0
  16. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/core_numpy.py +0 -0
  17. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/core_torch.py +0 -0
  18. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/booster.py +0 -0
  19. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/hashtable.py +0 -0
  20. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/subgrid.py +0 -0
  21. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/booster.py +0 -0
  22. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/hashtable.py +0 -0
  23. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/subgrid.py +0 -0
  24. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/sampler.py +0 -0
  25. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/views.py +0 -0
  26. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/dependency_links.txt +0 -0
  27. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/requires.txt +0 -0
  28. {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: squarenet
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Gridification for point clouds in any dimension (fast greedy optimal transport through Cartesian Sort).
5
5
  Author-email: ArmanddeCacqueray <armanddecacqueray@sfr.fr>
6
6
  Project-URL: Homepage, https://github.com/ArmanddeCacqueray/SquareNet
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "squarenet"
7
- version = "1.3.2"
7
+ version = "1.3.4"
8
8
  description = "Gridification for point clouds in any dimension (fast greedy optimal transport through Cartesian Sort)."
9
9
  authors = [{ name = "ArmanddeCacqueray", email = "armanddecacqueray@sfr.fr" }]
10
10
  readme = "README.md"
@@ -0,0 +1,4 @@
1
+ from .squarenet import SquareNet
2
+
3
+ __all__ = ["SquareNet", "samplepoints", "plotpoints", "sqplot", "carthesian_sort"]
4
+ __version__ = "1.3.4"
@@ -492,7 +492,16 @@ def sqplot(grid, verbose, style="checkerboard", animate=False,
492
492
  print(f"ffmpeg unavailable. Npoints = {rounded} and style is 'scatter' -> could take 1/2 minutes")
493
493
  else:
494
494
  print(f"ffmpeg unavailable. Npoints = {rounded} -> could take 20/30 seconds")
495
- ani.save(save_path, writer=writer, fps=full_cfg["fps"])
495
+ if has_ffmpeg:
496
+ from matplotlib.animation import FFMpegWriter
497
+ # On passe le fps ICI, lors de la création de l'objet
498
+ writer = FFMpegWriter(fps=full_cfg["fps"], codec="h264", bitrate=-1)
499
+ # Et on ne le passe PLUS dans .save()
500
+ ani.save(save_path, writer=writer)
501
+ else:
502
+ writer = "pillow"
503
+ # Avec le string "pillow", on doit passer le fps dans .save()
504
+ ani.save(save_path, writer=writer, fps=full_cfg["fps"])
496
505
  else:
497
506
  if cfg["show"]:
498
507
  plt.show()
@@ -0,0 +1,67 @@
1
+ import numpy as np
2
+
3
+
4
+ def from_backend(x):
5
+ """Convert any supported array/tensor to a NumPy ndarray."""
6
+ if isinstance(x, np.ndarray):
7
+ return x
8
+ module = type(x).__module__.split(".")[0]
9
+ if module == "torch":
10
+ return x.detach().cpu().numpy()
11
+ return np.asarray(x)
12
+
13
+
14
+ def get_backend_device(x):
15
+ """Return (backend, device) for a supported array."""
16
+ if isinstance(x, np.ndarray):
17
+ return "numpy", "cpu"
18
+ module = type(x).__module__.split(".")[0]
19
+ if module == "torch":
20
+ return "torch", str(x.device)
21
+ if module in ("jax", "jaxlib"):
22
+ dev = getattr(x, "device", None)
23
+ return "jax", str(dev) if dev is not None else "unknown"
24
+ return "unknown", None
25
+
26
+
27
+ def to_backend(x, backend="numpy"):
28
+ """
29
+ Convert arrays between NumPy, Torch and JAX.
30
+
31
+ Philosophy
32
+ ----------
33
+ - If backend already match, return x unchanged.
34
+ - Otherwise always convert through NumPy.
35
+ """
36
+ current_backend, current_device = get_backend_device(x)
37
+ # ------------------------------------------------------------------
38
+ # Already on requested backend/device
39
+ # ------------------------------------------------------------------
40
+ if backend == current_backend:
41
+ return x
42
+ # ------------------------------------------------------------------
43
+ # Convert through NumPy
44
+ # ------------------------------------------------------------------
45
+ arr = from_backend(x)
46
+ # ------------------------------------------------------------------
47
+ # NumPy
48
+ # ------------------------------------------------------------------
49
+ if backend == "numpy":
50
+ return arr
51
+ # ------------------------------------------------------------------
52
+ # Torch
53
+ # ------------------------------------------------------------------
54
+ if backend == "torch":
55
+ import torch
56
+ device = "cuda" if torch.cuda.is_available() else "cpu"
57
+ return torch.as_tensor(arr, device=torch.device(device))
58
+ # ------------------------------------------------------------------
59
+ # JAX
60
+ # ------------------------------------------------------------------
61
+ if backend == "jax":
62
+ import jax.numpy as jnp
63
+ out = jnp.asarray(arr)
64
+ return out
65
+ raise ValueError(
66
+ f"Unknown backend '{backend}'. Expected 'numpy', 'torch' or 'jax'."
67
+ )
@@ -5,7 +5,8 @@ from .core import carthesian_sort
5
5
  from .artist import sqplot, default_config
6
6
  from .sampler import samplepoints
7
7
  from .neighbormap import neighbormap
8
- from .utils import make_stencil, fill_in, dualgrid, dualgridflat, from_backend, to_backend, printmatrix
8
+ from .utils import make_stencil, fill_in, dualgrid, dualgridflat, printmatrix
9
+ from .backends import from_backend, to_backend
9
10
 
10
11
  class SquareNet:
11
12
  """
@@ -58,7 +59,6 @@ class SquareNet:
58
59
  self.max_iter = max_iter
59
60
  self.verbose = verbose
60
61
  self.backend = backend
61
- self.device = "cpu"
62
62
  self._torchdevice = "cpu"
63
63
 
64
64
  if backend not in {"numpy", "jax", "torch"}:
@@ -90,7 +90,7 @@ class SquareNet:
90
90
  import torch
91
91
  self.xp = torch
92
92
  if torch.cuda.is_available():
93
- self.device = torch.device("cuda")
93
+ self._torchdevice = torch.device("cuda")
94
94
 
95
95
  self.warnings_ = warnings_
96
96
  if stencil is not None:
@@ -104,7 +104,7 @@ class SquareNet:
104
104
  # Internal utilities
105
105
  # ------------------------------------------------------------------
106
106
  def _to_backend(self, x):
107
- return to_backend(x, backend = self.backend, device = self.device, warnings_ = self.warnings_)
107
+ return to_backend(x, backend = self.backend, warnings_ = self.warnings_)
108
108
 
109
109
  def _reset_state(self):
110
110
  """Reset internal state to initial configuration."""
@@ -228,16 +228,12 @@ class SquareNet:
228
228
  see ``squarenet.core``
229
229
  """
230
230
  old_backend = self.backend
231
- old_device = self.device
232
-
233
231
  if self._torchdevice != "cpu":
234
- #just for the fit, will be updated after
232
+ #We will fit on GPU with torch
235
233
  self.backend = "torch"
236
- self.device = self._torchdevice
237
234
  else:
238
- #just for the fit, will be updated after
235
+ #We will fit on CPU with numpy
239
236
  self.backend = "numpy"
240
- self.device = "cpu"
241
237
 
242
238
  true_g = np.array(self.gridshape)
243
239
  true_g = true_g[true_g > 1]
@@ -303,7 +299,6 @@ class SquareNet:
303
299
  )
304
300
 
305
301
  self.backend = old_backend
306
- self.device = old_device
307
302
  self.grid = self._to_backend(grid)
308
303
  self.points = self._to_backend(points)
309
304
  # --------------------------------------------------
@@ -213,82 +213,6 @@ def project(gridpoints, feature_axes=(0, 1), index=0):
213
213
 
214
214
  return x
215
215
 
216
-
217
- def from_backend(x):
218
- """
219
- Safely convert Torch, JAX, or array-like objects back to Numpy.
220
- """
221
- # 1. Already a Numpy array
222
- if isinstance(x, np.ndarray):
223
- return x
224
-
225
- # 2. PyTorch tensor
226
- if hasattr(x, "detach"):
227
- return x.detach().cpu().numpy()
228
-
229
- # 3. JAX arrays or any object with __array__ protocol (Pandas, etc.)
230
- return np.asarray(x)
231
-
232
- def to_backend(x, backend="numpy", device="cpu", warnings_=True):
233
- """
234
- Convert arrays/tensors between Numpy, Torch, and JAX.
235
- Utilizes DLPack for zero-copy transfers across frameworks when possible.
236
- """
237
- # Identify input framework without heavy imports
238
- in_type = type(x).__module__.split('.')[0]
239
-
240
- # ---------------------------------------------------------
241
- # 1. Target: NUMPY
242
- # ---------------------------------------------------------
243
- if backend == "numpy":
244
- return from_backend(x)
245
-
246
- # ---------------------------------------------------------
247
- # 2. Target: TORCH
248
- # ---------------------------------------------------------
249
- elif backend == "torch":
250
- import torch
251
- tgt_dev = torch.device(device)
252
-
253
- if in_type == "torch":
254
- if warnings_ and x.device.type != "cpu" and tgt_dev.type == "cpu":
255
- warn("Downgrading tensor: initial device was GPU but asked for CPU.")
256
- return x.to(tgt_dev)
257
-
258
- elif in_type in ["jax", "jaxlib"]:
259
- # Zero-copy JAX to Torch via DLPack
260
- return torch.from_dlpack(x).to(tgt_dev)
261
-
262
- return torch.as_tensor(x, device=tgt_dev)
263
-
264
- # ---------------------------------------------------------
265
- # 3. Target: JAX
266
- # ---------------------------------------------------------
267
- elif backend == "jax":
268
- import jax
269
- import jax.numpy as jnp
270
-
271
- # JAX uses "gpu" instead of "cuda"
272
- device = "cpu" if "cpu" in str(device) else "gpu"
273
- try:
274
- tgt_dev = jax.devices(device)[0]
275
- except RuntimeError:
276
- tgt_dev = None
277
-
278
- if in_type == "torch":
279
- import torch.utils.dlpack
280
- # DLPack requires contiguous memory
281
- x = x if x.is_contiguous() else x.contiguous()
282
- j_arr = jax.dlpack.from_dlpack(torch.utils.dlpack.to_dlpack(x))
283
- return jax.device_put(j_arr, tgt_dev) if tgt_dev else j_arr
284
-
285
- elif in_type in ["jax", "jaxlib"]:
286
- return jax.device_put(x, tgt_dev) if tgt_dev else x
287
-
288
- return jax.device_put(x, tgt_dev) if tgt_dev else jnp.asarray(x)
289
-
290
- raise ValueError(f"Unknown backend: '{backend}'. Expected 'numpy', 'torch', or 'jax'.")
291
-
292
216
  def progress_bar(it, total, bar_length=30):
293
217
  progress = it / total
294
218
  filled = int(bar_length * progress)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: squarenet
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Gridification for point clouds in any dimension (fast greedy optimal transport through Cartesian Sort).
5
5
  Author-email: ArmanddeCacqueray <armanddecacqueray@sfr.fr>
6
6
  Project-URL: Homepage, https://github.com/ArmanddeCacqueray/SquareNet
@@ -2,6 +2,7 @@ README.md
2
2
  pyproject.toml
3
3
  src/squarenet/__init__.py
4
4
  src/squarenet/artist.py
5
+ src/squarenet/backends.py
5
6
  src/squarenet/core.py
6
7
  src/squarenet/neighbormap.py
7
8
  src/squarenet/sampler.py
@@ -1,4 +0,0 @@
1
- from .squarenet import SquareNet
2
-
3
- __all__ = ["SquareNet", "samplepoints", "place_at", "plotpoints", "sqplot", "carthesian_sort"]
4
- __version__ = "1.3.2"
File without changes
File without changes