Repository: BAMWelDX/weldx

Issue:
support quantities in WXRotation.from_euler()
Now that we mostly use quantities we should add support to `WXRotation.from_euler()`

- allow quantities in ASDF schema
- use pint decorator
- maybe deprecate `tf.rotation_matrix_X` functions in favour of `WXRotation`

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=h1) Report
> Merging [#318](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=desc) (021262d) into [master](https://codecov.io/gh/BAMWelDX/weldx/commit/bd643850b670a9da087e7739406bc7074a0dcc84?el=desc) (bd64385) will **decrease** coverage by `0.01%`.
> The diff coverage is `90.00%`.

[![Impacted file tree graph](https://codecov.io/gh/BAMWelDX/weldx/pull/318/graphs/tree.svg?width=650&height=150&src=pr&token=wdof1qQTsn)](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #318      +/-   ##
==========================================
- Coverage   96.86%   96.84%   -0.02%     
==========================================
  Files          82       82              
  Lines        4724     4729       +5     
==========================================
+ Hits         4576     4580       +4     
- Misses        148      149       +1     
```


| [Impacted Files](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [weldx/transformations/rotation.py](https://codecov.io/gh/BAMWelDX/weldx/pull/318/diff?src=pr&el=tree#diff-d2VsZHgvdHJhbnNmb3JtYXRpb25zL3JvdGF0aW9uLnB5) | `97.61% <85.71%> (-2.39%)` | :arrow_down: |
| [...x/asdf/tags/weldx/core/transformations/rotation.py](https://codecov.io/gh/BAMWelDX/weldx/pull/318/diff?src=pr&el=tree#diff-d2VsZHgvYXNkZi90YWdzL3dlbGR4L2NvcmUvdHJhbnNmb3JtYXRpb25zL3JvdGF0aW9uLnB5) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=footer). Last update [bd64385...021262d](https://codecov.io/gh/BAMWelDX/weldx/pull/318?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

pep8speaks: Hello @CagtayFabry! Thanks for updating this PR. 

* In the file [`tests/asdf_tests/test_asdf_core.py`](https://github.com/BAMWelDX/weldx/blob/e028eb8c611c7476fdf26a2fc52be30059ed74e2/tests/asdf_tests/test_asdf_core.py):

> [Line 57:22](https://github.com/BAMWelDX/weldx/blob/e028eb8c611c7476fdf26a2fc52be30059ed74e2/tests/asdf_tests/test_asdf_core.py#L57): [E231](https://duckduckgo.com/?q=pep8%20E231) missing whitespace after ','







Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5efffe..f89c75c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Release Notes
 
+
+## 0.4.0 (unreleased)
+
+### changes
+- `WXRotation.from_euler()` now accepts a `pint.Quantity` as input. [[#318]](https://github.com/BAMWelDX/weldx/pull/318)
+
 ## 0.3.3 (30.03.2021)
 
 This is a bugfix release to correctly include the asdf schema files in conda
diff --git a/weldx/asdf/tags/weldx/core/transformations/rotation.py b/weldx/asdf/tags/weldx/core/transformations/rotation.py
index cbe4037..3158a68 100644
--- a/weldx/asdf/tags/weldx/core/transformations/rotation.py
+++ b/weldx/asdf/tags/weldx/core/transformations/rotation.py
@@ -99,12 +99,4 @@ class WXRotationTypeASDF(WeldxType):
         elif "rotvec" in tree:
             return WXRotation.from_rotvec(tree["rotvec"])
         elif "angles" in tree:
-            if "degree" in str(tree["angles"].units):
-                angles = tree["angles"].to("degree").magnitude
-                degrees = True
-            else:
-                angles = tree["angles"].to("rad").magnitude
-                degrees = False
-            return WXRotation.from_euler(
-                seq=tree["sequence"], angles=angles, degrees=degrees
-            )
+            return WXRotation.from_euler(seq=tree["sequence"], angles=tree["angles"])
diff --git a/weldx/transformations/rotation.py b/weldx/transformations/rotation.py
index fd5e28a..1d5cd3d 100644
--- a/weldx/transformations/rotation.py
+++ b/weldx/transformations/rotation.py
@@ -1,6 +1,9 @@
 """Contains tools to handle rotations."""
 
+from typing import List, Union
+
 import numpy as np
+import pint
 from scipy.spatial.transform import Rotation as _Rotation
 
 from weldx.constants import WELDX_UNIT_REGISTRY as UREG
@@ -100,13 +103,24 @@ class WXRotation(_Rotation):
         return rot
 
     @classmethod
+    @UREG.check(None, None, "[]", None)
     def from_euler(
-        cls, seq: str, angles, degrees: bool = False
+        cls,
+        seq: str,
+        angles: Union[pint.Quantity, np.ndarray, List[float], List[List[float]]],
+        degrees: bool = False,
     ) -> "WXRotation":  # noqa
         """Initialize from euler angles.
 
         See `scipy.spatial.transform.Rotation.from_euler` docs for details.
         """
+
+        if isinstance(angles, pint.Quantity):
+            if str(angles.u) == "dimensionless":
+                angles = angles.to("rad")
+            degrees = "rad" not in str(angles.u)
+            angles = angles.m
+
         rot = super().from_euler(seq=seq, angles=angles, degrees=degrees)
         setattr(
             rot,


Test patch:
diff --git a/tests/asdf_tests/test_asdf_core.py b/tests/asdf_tests/test_asdf_core.py
index ce4ec89..6217a54 100644
--- a/tests/asdf_tests/test_asdf_core.py
+++ b/tests/asdf_tests/test_asdf_core.py
@@ -36,17 +36,26 @@ _base_rotation = Rotation.from_euler(
         WXRotation.from_rotvec(_base_rotation.as_rotvec()),
         WXRotation.from_euler(seq="xyz", angles=[10, 20, 60], degrees=True),
         WXRotation.from_euler(seq="xyz", angles=[0.2, 1.3, 3.14], degrees=False),
+        WXRotation.from_euler(seq="xyz", angles=Q_([10, 20, 60], "degree")),
+        WXRotation.from_euler(seq="xyz", angles=Q_([0.2, 1.3, 3.14], "rad")),
+        WXRotation.from_euler(seq="xyz", angles=Q_([0.2, 1.3, 3.14], "")),
         WXRotation.from_euler(seq="XYZ", angles=[10, 20, 60], degrees=True),
         WXRotation.from_euler(seq="y", angles=[10, 60, 40, 90], degrees=True),
         WXRotation.from_euler(seq="Z", angles=[10, 60, 40, 90], degrees=True),
         WXRotation.from_euler(
             seq="xy", angles=[[10, 10], [60, 60], [40, 40], [70, 75]], degrees=True
         ),
+        WXRotation.from_euler(
+            seq="xy", angles=Q_([[10, 10], [60, 60], [40, 40], [70, 75]], "degree")
+        ),
     ],
 )
 def test_rotation(inputs):
     data = _write_read_buffer({"rot": inputs})
-    assert np.allclose(data["rot"].as_quat(), inputs.as_quat())
+    r = data["rot"]
+    assert np.allclose(r.as_quat(), inputs.as_quat())
+    if hasattr(inputs, "wx_meta"):
+        assert r.wx_meta == inputs.wx_meta
 
 
 def test_rotation_euler_exception():