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/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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any