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.
- {squarenet-1.3.2 → squarenet-1.3.4}/PKG-INFO +1 -1
- {squarenet-1.3.2 → squarenet-1.3.4}/pyproject.toml +1 -1
- squarenet-1.3.4/src/squarenet/__init__.py +4 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/artist.py +10 -1
- squarenet-1.3.4/src/squarenet/backends.py +67 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/squarenet.py +6 -11
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/utils.py +0 -76
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/PKG-INFO +1 -1
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/SOURCES.txt +1 -0
- squarenet-1.3.2/src/squarenet/__init__.py +0 -4
- {squarenet-1.3.2 → squarenet-1.3.4}/README.md +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/setup.cfg +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/core.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/data/__init__.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/neighbormap.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/core_numpy.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/core_torch.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/booster.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/hashtable.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/numpy/subgrid.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/booster.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/hashtable.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/optim/torch/subgrid.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/sampler.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet/views.py +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/dependency_links.txt +0 -0
- {squarenet-1.3.2 → squarenet-1.3.4}/src/squarenet.egg-info/requires.txt +0 -0
- {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.
|
|
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.
|
|
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"
|
|
@@ -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
|
-
|
|
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,
|
|
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.
|
|
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,
|
|
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
|
-
#
|
|
232
|
+
#We will fit on GPU with torch
|
|
235
233
|
self.backend = "torch"
|
|
236
|
-
self.device = self._torchdevice
|
|
237
234
|
else:
|
|
238
|
-
#
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|