nanomanifold 0.1.1__py3-none-any.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 nanomanifold might be problematic. Click here for more details.
- nanomanifold/SE3/__init__.py +21 -0
- nanomanifold/SE3/canonicalize.py +25 -0
- nanomanifold/SE3/conversions/__init__.py +9 -0
- nanomanifold/SE3/conversions/matrix.py +57 -0
- nanomanifold/SE3/conversions/rt.py +30 -0
- nanomanifold/SE3/exp.py +73 -0
- nanomanifold/SE3/inverse.py +37 -0
- nanomanifold/SE3/log.py +75 -0
- nanomanifold/SE3/multiply.py +48 -0
- nanomanifold/SE3/transform_points.py +34 -0
- nanomanifold/SO3/__init__.py +35 -0
- nanomanifold/SO3/canonicalize.py +17 -0
- nanomanifold/SO3/conversions/__init__.py +14 -0
- nanomanifold/SO3/conversions/axis_angle.py +63 -0
- nanomanifold/SO3/conversions/euler.py +149 -0
- nanomanifold/SO3/conversions/matrix.py +79 -0
- nanomanifold/SO3/distance.py +52 -0
- nanomanifold/SO3/exp.py +25 -0
- nanomanifold/SO3/hat.py +36 -0
- nanomanifold/SO3/inverse.py +16 -0
- nanomanifold/SO3/log.py +25 -0
- nanomanifold/SO3/multiply.py +40 -0
- nanomanifold/SO3/rotate_points.py +50 -0
- nanomanifold/SO3/slerp.py +69 -0
- nanomanifold/SO3/vee.py +28 -0
- nanomanifold/SO3/weighted_mean.py +89 -0
- nanomanifold/__init__.py +3 -0
- nanomanifold/common.py +25 -0
- nanomanifold-0.1.1.dist-info/METADATA +112 -0
- nanomanifold-0.1.1.dist-info/RECORD +31 -0
- nanomanifold-0.1.1.dist-info/WHEEL +4 -0
nanomanifold/common.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import array_api_compat
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_namespace(array):
|
|
5
|
+
return array_api_compat.get_namespace(array)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_namespace_by_name(name: str):
|
|
9
|
+
if name == "numpy":
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
ones = np.ones(1)
|
|
13
|
+
return get_namespace(ones)
|
|
14
|
+
|
|
15
|
+
elif name == "torch":
|
|
16
|
+
import torch
|
|
17
|
+
|
|
18
|
+
ones = torch.ones(1)
|
|
19
|
+
return get_namespace(ones)
|
|
20
|
+
|
|
21
|
+
elif name == "jax":
|
|
22
|
+
import jax.numpy as jnp
|
|
23
|
+
|
|
24
|
+
ones = jnp.ones(1)
|
|
25
|
+
return get_namespace(ones)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nanomanifold
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: SO3/SE3 operations on any backend
|
|
5
|
+
Author-email: Andrea Boscolo Camiletto <abcamiletto@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: array-api-compat>=1.12.0
|
|
8
|
+
Requires-Dist: jaxtyping>=0.3.2
|
|
9
|
+
Requires-Dist: numpy>=2.3.2
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# nanomanifold
|
|
13
|
+
|
|
14
|
+
Fast, batched and differentiable SO3/SE3 transforms for any backend (NumPy, PyTorch, JAX, ...)
|
|
15
|
+
Works directly on arrays, defined as:
|
|
16
|
+
|
|
17
|
+
- **SO3**: unit quaternions `[w, x, y, z]` for 3D rotations, shape `(..., 4)`
|
|
18
|
+
- **SE3**: concatenated `[quat, translation]`, shape `(..., 7)`
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import numpy as np
|
|
22
|
+
from nanomanifold import SO3, SE3
|
|
23
|
+
|
|
24
|
+
# Rotations stored as quaternion arrays [w,x,y,z]
|
|
25
|
+
q = SO3.from_axis_angle(np.array([0, 0, 1]), np.pi/4) # 45° around Z
|
|
26
|
+
points = np.array([[1, 0, 0], [0, 1, 0]])
|
|
27
|
+
rotated = SO3.rotate_points(q, points)
|
|
28
|
+
|
|
29
|
+
# Rigid transforms stored as 7D arrays [quat, translation]
|
|
30
|
+
T = SE3.from_rt(q, np.array([1, 0, 0])) # rotation + translation
|
|
31
|
+
transformed = SE3.transform_points(T, points)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
**Array-based API** — all functions operate directly on arrays from any backend
|
|
37
|
+
**Backend agnostic** — works with NumPy, PyTorch, JAX, CuPy, Dask, and more
|
|
38
|
+
**Batched operations** — process thousands of transforms at once
|
|
39
|
+
**Differentiable** — automatic gradients where supported (PyTorch/JAX)
|
|
40
|
+
**Memory efficient** — quaternions instead of matrices
|
|
41
|
+
**Numerically stable** — handles edge cases and singularities
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
### Rotations (SO3)
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from nanomanifold import SO3
|
|
49
|
+
|
|
50
|
+
# Create rotations
|
|
51
|
+
q1 = SO3.from_axis_angle([1, 0, 0], np.pi/2) # 90° around X
|
|
52
|
+
q2 = SO3.from_euler([0, 0, np.pi/4]) # 45° around Z
|
|
53
|
+
q3 = SO3.from_matrix(rotation_matrix)
|
|
54
|
+
|
|
55
|
+
# Compose and interpolate
|
|
56
|
+
q_combined = SO3.multiply(q1, q2)
|
|
57
|
+
q_halfway = SO3.slerp(q1, q2, t=0.5)
|
|
58
|
+
|
|
59
|
+
# Apply to points
|
|
60
|
+
points = np.array([[1, 0, 0], [0, 1, 0]])
|
|
61
|
+
rotated = SO3.rotate_points(q_combined, points)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Rigid Transforms (SE3)
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from nanomanifold import SE3
|
|
68
|
+
|
|
69
|
+
# Create transforms
|
|
70
|
+
T1 = SE3.from_rt(q1, [1, 2, 3]) # rotation + translation
|
|
71
|
+
T2 = SE3.from_matrix(transformation_matrix)
|
|
72
|
+
|
|
73
|
+
# Compose transforms
|
|
74
|
+
T_combined = SE3.multiply(T1, T2)
|
|
75
|
+
T_inverse = SE3.inverse(T_combined)
|
|
76
|
+
|
|
77
|
+
# Apply to points
|
|
78
|
+
transformed = SE3.transform_points(T_combined, points)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
### SO3 (3D Rotations)
|
|
84
|
+
|
|
85
|
+
| Function | Input → Output | Description |
|
|
86
|
+
| ------------------------------ | ----------------------------------- | --------------------------- |
|
|
87
|
+
| `from_axis_angle(axis, angle)` | `(...,3), (...) → (...,4)` | Create from axis-angle |
|
|
88
|
+
| `from_euler(angles)` | `(...,3) → (...,4)` | Create from Euler angles |
|
|
89
|
+
| `from_matrix(R)` | `(...,3,3) → (...,4)` | Create from rotation matrix |
|
|
90
|
+
| `multiply(q1, q2)` | `(...,4), (...,4) → (...,4)` | Compose rotations |
|
|
91
|
+
| `slerp(q1, q2, t)` | `(...,4), (...,4), (...) → (...,4)` | Spherical interpolation |
|
|
92
|
+
| `rotate_points(q, points)` | `(...,4), (...,N,3) → (...,N,3)` | Rotate 3D points |
|
|
93
|
+
|
|
94
|
+
### SE3 (Rigid Transforms)
|
|
95
|
+
|
|
96
|
+
| Function | Input → Output | Description |
|
|
97
|
+
| ----------------------------- | -------------------------------- | ---------------------------------- |
|
|
98
|
+
| `from_rt(q, t)` | `(...,4), (...,3) → (...,7)` | Create from rotation + translation |
|
|
99
|
+
| `from_matrix(T)` | `(...,4,4) → (...,7)` | Create from 4×4 matrix |
|
|
100
|
+
| `multiply(T1, T2)` | `(...,7), (...,7) → (...,7)` | Compose transforms |
|
|
101
|
+
| `inverse(T)` | `(...,7) → (...,7)` | Invert transform |
|
|
102
|
+
| `transform_points(T, points)` | `(...,7), (...,N,3) → (...,N,3)` | Transform 3D points |
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install nanomanifold
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
nanomanifold/__init__.py,sha256=VuueSV8KaH4sg23rqB_sKIoI4MHhHgWfswH30hnMe0M,49
|
|
2
|
+
nanomanifold/common.py,sha256=xM2CEafWnf9TM9r3cK3lbGap2sdGpk9TxqN6wfxOHlA,487
|
|
3
|
+
nanomanifold/SE3/__init__.py,sha256=2VqjGg0ZKxI9Uqq0oVGTEEQYE2ISy2AwRsDhOq3LmbY,462
|
|
4
|
+
nanomanifold/SE3/canonicalize.py,sha256=kQ_Pf_wILTxTxYhEbhwc_kgIbvUQBbSE5jqP45INmrE,692
|
|
5
|
+
nanomanifold/SE3/exp.py,sha256=qn0aUHQR5q9wT5BMz6PUhW733g9_SNedEdoxa8uWv3U,2466
|
|
6
|
+
nanomanifold/SE3/inverse.py,sha256=UVUkqKwnIM8tNtgLXoZ5OhXSXaa2TT8kszaZaGtXXYI,919
|
|
7
|
+
nanomanifold/SE3/log.py,sha256=JTm1Tg1qJmata8vrKyYzztOy3LSTdx2dk5jwEzJeI0U,2600
|
|
8
|
+
nanomanifold/SE3/multiply.py,sha256=ChrxGyOYDsgnaAlrIc8vXwlltPckQNUohxjfrSlaroc,1467
|
|
9
|
+
nanomanifold/SE3/transform_points.py,sha256=2ELZCrhqEQap8EUbOPQxGSqn9zLY18lzrbwVgBIujyA,901
|
|
10
|
+
nanomanifold/SE3/conversions/__init__.py,sha256=6MEel9koLk-YVJgzg-oTorl4VNi68msmLr4bIsQqb0Q,153
|
|
11
|
+
nanomanifold/SE3/conversions/matrix.py,sha256=6ePkIyPl4xc-1DeX5RqP2j2Vofi8KUFt8v68I3jZGmo,1494
|
|
12
|
+
nanomanifold/SE3/conversions/rt.py,sha256=rRY17oa2bWxuf81ycZGE0qQc0kwQMtxKKY7lL2C82ns,842
|
|
13
|
+
nanomanifold/SO3/__init__.py,sha256=OgI8iCNwke19_mSzcKT4wBFjwwxaD4rvc8S0OSTJRP8,808
|
|
14
|
+
nanomanifold/SO3/canonicalize.py,sha256=QFW4J9Ep6bkcu9y6JbygxLaU0aDle-HFJh7uG-ZgTaw,403
|
|
15
|
+
nanomanifold/SO3/distance.py,sha256=2U4YEG2xmqTdu6jShmRGBvp2RNPr924iLxuaMF8gYx0,1672
|
|
16
|
+
nanomanifold/SO3/exp.py,sha256=jBun_y-4ekAzQADLIiYIh28xi7OzfibkinamtOJKN9g,872
|
|
17
|
+
nanomanifold/SO3/hat.py,sha256=K7OyXhCTfTpLh-OoQHP7wwBPjTu1YTV22iC1jXy5kms,766
|
|
18
|
+
nanomanifold/SO3/inverse.py,sha256=D_WjUJz5dSJv1zYfLa2xi03K-tJZ4UrQYbH_8Tk9iPA,390
|
|
19
|
+
nanomanifold/SO3/log.py,sha256=pdR2rtbxsfLqXcExPRAodQRhG7MFoGkJyxzG29eXQuQ,809
|
|
20
|
+
nanomanifold/SO3/multiply.py,sha256=wSAuJaLqTZJTsUlPrLJgKqDdzk81J-6w4xnPHK5UjpU,1173
|
|
21
|
+
nanomanifold/SO3/rotate_points.py,sha256=JiknHDLMmwl1AIzLgppzsP0kq3McTYAHxnY_f3bb2RM,1364
|
|
22
|
+
nanomanifold/SO3/slerp.py,sha256=t14CBV8BbLgkqvg6Oa-RzvB1ivKMtpxuGvejSCJwXc4,2303
|
|
23
|
+
nanomanifold/SO3/vee.py,sha256=OiyiH0g0FKXzIA-EBnxqW-79XNCiZcbovCraR1T9JoI,589
|
|
24
|
+
nanomanifold/SO3/weighted_mean.py,sha256=uOGbqTMmXLIPwqsuCa_pGRfYSbse9zga1wexQuyipgU,3418
|
|
25
|
+
nanomanifold/SO3/conversions/__init__.py,sha256=lJVUaKfkiQvcUsSIQYE4T6t5P64jRRhK_MbnICxdEhM,302
|
|
26
|
+
nanomanifold/SO3/conversions/axis_angle.py,sha256=g-YNicc2paE3CBBTUYc_IqzFGgCCJbq8OCDC3QyEFas,1712
|
|
27
|
+
nanomanifold/SO3/conversions/euler.py,sha256=vjuUFZGHN2iyvrnJXSqcYtzTnh7pIQInPPC3XckT2L8,4486
|
|
28
|
+
nanomanifold/SO3/conversions/matrix.py,sha256=ngKi5NSN3G2AA_ggUaq1095_u-L79q8nW3_3w9zMuNI,2830
|
|
29
|
+
nanomanifold-0.1.1.dist-info/METADATA,sha256=s6Rq6byQFxPtVzYClzqs8qnllCiedeTxsEy6gOxukBU,4092
|
|
30
|
+
nanomanifold-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
31
|
+
nanomanifold-0.1.1.dist-info/RECORD,,
|