From 96e64fc6e0a6fce1b1d72d399a980785b59c0269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 21:15:50 +0200 Subject: [PATCH 1/8] Replace assert-or-raise with better check-or-raise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/vector/vector3d.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orix/vector/vector3d.py b/orix/vector/vector3d.py index a565ba71..ea62b36d 100644 --- a/orix/vector/vector3d.py +++ b/orix/vector/vector3d.py @@ -676,7 +676,8 @@ def get_nearest( Vector3d (1,) [[0.6 0. 0. ]] """ - assert self.size == 1, "`get_nearest` only works for single vectors." + if self.size != 1: + raise AttributeError("`get_nearest` only works for single vectors") tiebreak = Vector3d.zvector() if tiebreak is None else tiebreak eps = 1e-9 if inclusive else 0 cosines = x.dot(self) From 9645bdfa2bc7d18fb1db2565ce619dce17697e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 21:19:13 +0200 Subject: [PATCH 2/8] List @IMBalENce among contributors according to line additions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- .zenodo.json | 5 +++++ orix/__init__.py | 1 + 2 files changed, 6 insertions(+) diff --git a/.zenodo.json b/.zenodo.json index 9b81059b..783e087a 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -34,6 +34,11 @@ "name": "Anders Christian Mathisen", "affiliation": "Norwegian University of Science and Technology" }, + { + "name": "Zhou Xu", + "orcid": "0000-0002-7599-1166", + "affiliation": "Monash Centre for Electron Microscopy" + }, { "name": "Carter Francis", "orcid": "0000-0003-2564-1851", diff --git a/orix/__init__.py b/orix/__init__.py index c3bb483d..283e5019 100644 --- a/orix/__init__.py +++ b/orix/__init__.py @@ -13,6 +13,7 @@ "Duncan Johnstone", "Niels Cautaerts", "Anders Christian Mathisen", + "Zhou Xu", "Carter Francis", "Simon Høgås", "Viljar Johan Femoen", From 56629c37244b5b7e8665f16ee427366b6434ce25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 21:28:47 +0200 Subject: [PATCH 3/8] Don't run test workflow for branches named 'pre-commit-ci-update-config' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e98c4988..6cb5c4ca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,11 +4,12 @@ on: push: branches: - '*' + branches-ignore: + - 'pre-commit-ci-update-config' pull_request: branches: - '*' workflow_dispatch: - workflow: '*' jobs: code: From 1cdc59a8f4567c12933261c0c58584740198349b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 22:01:04 +0200 Subject: [PATCH 4/8] Improve type hints in the Miller class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/vector/miller.py | 95 +++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/orix/vector/miller.py b/orix/vector/miller.py index f8a573f8..e65e68bd 100644 --- a/orix/vector/miller.py +++ b/orix/vector/miller.py @@ -20,13 +20,23 @@ from copy import deepcopy from itertools import product -from typing import Optional, Tuple, Union +from typing import TYPE_CHECKING, Optional, Tuple, Union + +try: + # New in Python 3.11 + from typing import Self +except ImportError: # pragma: no cover + from typing_extensions import Self from diffpy.structure import Lattice import numpy as np from orix.vector import Vector3d +if TYPE_CHECKING: # pragma: no cover + from orix.crystal_map import Phase + from orix.quaternion import Symmetry + class Miller(Vector3d): r"""Direct crystal lattice vectors (uvw or UVTW) and reciprocal @@ -48,13 +58,12 @@ class Miller(Vector3d): Indices of direct lattice vector(s). Default is ``None``. UVTW Indices of direct lattice vector(s), often preferred over - ``uvw`` in trigonal and hexagonal lattices. Default is ``None``. + *uvw* in trigonal and hexagonal lattices. Default is ``None``. hkl Indices of reciprocal lattice vector(s). Default is ``None``. hkil - Indices of reciprocal lattice vector(s), often preferred - over ``hkl`` in trigonal and hexagonal lattices. Default is - ``None``. + Indices of reciprocal lattice vector(s), often preferred over + *hkl* in trigonal and hexagonal lattices. Default is ``None``. phase A phase with a crystal lattice and symmetry. Must be passed whenever direct or reciprocal lattice vectors are created. @@ -77,13 +86,8 @@ def __init__( UVTW: Union[np.ndarray, list, tuple, None] = None, hkl: Union[np.ndarray, list, tuple, None] = None, hkil: Union[np.ndarray, list, tuple, None] = None, - phase: Optional["orix.crystal_map.Phase"] = None, - ): - """Create a set of direct lattice vectors (uvw or UVTW) or - reciprocal lattice vectors (hkl or hkil) describing directions - with respect to a crystal reference frame defined by a phase's - crystal lattice and symmetry. - """ + phase: Optional["Phase"] = None, + ) -> None: n_passed = np.sum([i is not None for i in [xyz, uvw, UVTW, hkl, hkil]]) if n_passed == 0 or n_passed > 1: raise ValueError( @@ -134,7 +138,7 @@ def coordinate_format(self) -> str: return self._coordinate_format @coordinate_format.setter - def coordinate_format(self, value: str): + def coordinate_format(self, value: str) -> None: """Set the vector coordinate format.""" formats = ["xyz", "uvw", "UVTW", "hkl", "hkil"] if value not in formats: @@ -162,12 +166,12 @@ def hkl(self) -> np.ndarray: return _transform_space(self.data, "c", "r", self.phase.structure.lattice) @hkl.setter - def hkl(self, value: np.ndarray): + def hkl(self, value: np.ndarray) -> None: """Set the reciprocal lattice vectors.""" self.data = _transform_space(value, "r", "c", self.phase.structure.lattice) @property - def hkil(self): + def hkil(self) -> np.ndarray: r"""Return or set the reciprocal lattice vectors expressed as 4-index Miller-Bravais indices. @@ -181,7 +185,7 @@ def hkil(self): return _hkl2hkil(self.hkl) @hkil.setter - def hkil(self, value: np.ndarray): + def hkil(self, value: np.ndarray) -> None: """Set the reciprocal lattice vectors expressed as 4-index Miller-Bravais indices. """ @@ -223,12 +227,12 @@ def uvw(self) -> np.ndarray: return _transform_space(self.data, "c", "d", self.phase.structure.lattice) @uvw.setter - def uvw(self, value: np.ndarray): + def uvw(self, value: np.ndarray) -> None: """Set the direct lattice vectors.""" self.data = _transform_space(value, "d", "c", self.phase.structure.lattice) @property - def UVTW(self): + def UVTW(self) -> np.ndarray: r"""Return or set the direct lattice vectors expressed as 4-index Weber symbols. @@ -249,7 +253,7 @@ def UVTW(self): return _uvw2UVTW(self.uvw) @UVTW.setter - def UVTW(self, value): + def UVTW(self, value: np.ndarray) -> None: """Set the direct lattice vectors expressed as 4-index Weber symbols. """ @@ -341,7 +345,7 @@ def is_hexagonal(self) -> bool: return self.phase.is_hexagonal @property - def unit(self) -> Miller: + def unit(self) -> Self: """Return unit vectors.""" m = self.__class__(xyz=super().unit.data, phase=self.phase) m.coordinate_format = self.coordinate_format @@ -360,7 +364,7 @@ def __repr__(self) -> str: f"{name} {shape}, point group {symmetry}, {coordinate_format}\n" f"{data}" ) - def __getitem__(self, key) -> Miller: + def __getitem__(self, key) -> Self: """NumPy fancy indexing of vectors.""" m = self.__class__(xyz=self.data[key], phase=self.phase).deepcopy() m.coordinate_format = self.coordinate_format @@ -371,10 +375,11 @@ def __getitem__(self, key) -> Miller: @classmethod def from_highest_indices( cls, - phase: "orix.crystal_map.Phase", + phase: "Phase", uvw: Union[np.ndarray, list, tuple, None] = None, hkl: Union[np.ndarray, list, tuple, None] = None, - ) -> Miller: + include_zero_vector: bool = False, + ) -> Self: """Create a set of unique direct or reciprocal lattice vectors from three highest indices and a phase (crystal lattice and symmetry). @@ -401,9 +406,7 @@ def from_highest_indices( return cls(**init_kw).unique() @classmethod - def from_min_dspacing( - cls, phase: "orix.crystal_map.Phase", min_dspacing: float = 0.05 - ) -> Miller: + def from_min_dspacing(cls, phase: "Phase", min_dspacing: float = 0.05) -> Self: """Create a set of unique reciprocal lattice vectors with a a direct space interplanar spacing greater than a lower threshold. @@ -427,10 +430,10 @@ def from_min_dspacing( @classmethod def random( cls, - phase: "orix.crystal_map.Phase", + phase: "Phase", shape: Union[int, tuple] = 1, coordinate_format: str = "xyz", - ) -> Miller: + ) -> Self: """Create random Miller indices. Parameters @@ -464,11 +467,11 @@ def random( # --------------------- Other public methods --------------------- # - def deepcopy(self) -> Miller: + def deepcopy(self) -> Self: """Return a deepcopy of the instance.""" return deepcopy(self) - def round(self, max_index: int = 20) -> Miller: + def round(self, max_index: int = 20) -> Self: """Round a set of index triplet (Miller) or quartet (Miller-Bravais/Weber) to the *closest* smallest integers. @@ -496,9 +499,7 @@ def symmetrise( unique: bool = False, return_multiplicity: bool = False, return_index: bool = False, - ) -> Union[ - Miller, Tuple[Miller, np.ndarray], Tuple[Miller, np.ndarray, np.ndarray] - ]: + ) -> Union[Self, Tuple[Self, np.ndarray], Tuple[Self, np.ndarray, np.ndarray]]: """Return vectors symmetrically equivalent to the vectors. Parameters @@ -585,7 +586,7 @@ def symmetrise( def angle_with( self, - other: Miller, + other: Self, use_symmetry: bool = False, degrees: bool = False, ) -> np.ndarray: @@ -630,7 +631,7 @@ def angle_with( return angles - def cross(self, other: Miller): + def cross(self, other: Self) -> Self: """Return the cross products of the vectors with the other vectors, which is considered the zone axes between the vectors. @@ -652,7 +653,7 @@ def cross(self, other: Miller): m.coordinate_format = new_fmt[self.coordinate_format] return m - def dot(self, other: Miller) -> np.ndarray: + def dot(self, other: Self) -> np.ndarray: """Return the dot products of the vectors and the other vectors. Parameters @@ -669,7 +670,7 @@ def dot(self, other: Miller) -> np.ndarray: self._compatible_with(other, raise_error=True) return super().dot(other) - def dot_outer(self, other: Miller) -> np.ndarray: + def dot_outer(self, other: Self) -> np.ndarray: """Return the outer dot products of the vectors and the other vectors. @@ -687,7 +688,7 @@ def dot_outer(self, other: Miller) -> np.ndarray: self._compatible_with(other, raise_error=True) return super().dot_outer(other) - def flatten(self) -> Miller: + def flatten(self) -> Self: """Return the flattened vectors. Returns @@ -699,7 +700,7 @@ def flatten(self) -> Miller: m.coordinate_format = self.coordinate_format return m - def transpose(self, *axes: Optional[int]) -> Miller: + def transpose(self, *axes: Optional[int]) -> Self: """Return a new instance with the data transposed. The order may be undefined if :attr:`ndim` is originally 2. In @@ -725,7 +726,7 @@ def get_nearest(self, *args) -> NotImplemented: """NotImplemented.""" return NotImplemented - def mean(self, use_symmetry: bool = False) -> Miller: + def mean(self, use_symmetry: bool = False) -> Self: """Return the mean vector of the set of vectors. Parameters @@ -745,7 +746,7 @@ def mean(self, use_symmetry: bool = False) -> Miller: m.coordinate_format = self.coordinate_format return m - def reshape(self, *shape: Union[int, tuple]) -> Miller: + def reshape(self, *shape: Union[int, tuple]) -> Self: """Return a new instance with the vectors reshaped. Parameters @@ -764,7 +765,7 @@ def reshape(self, *shape: Union[int, tuple]) -> Miller: def unique( self, use_symmetry: bool = False, return_index: bool = False - ) -> Union[Miller, Tuple[Miller, np.ndarray]]: + ) -> Union[Self, Tuple[Self, np.ndarray]]: """Unique vectors in ``self``. Parameters @@ -809,9 +810,7 @@ def unique( else: return m - def in_fundamental_sector( - self, symmetry: Optional["orix.quaternion.Symmetry"] = None - ) -> Miller: + def in_fundamental_sector(self, symmetry: Optional["Symmetry"] = None) -> Self: """Project Miller indices to a symmetry's fundamental sector (inverse pole figure). @@ -858,7 +857,7 @@ def in_fundamental_sector( # -------------------- Other private methods --------------------- # - def _compatible_with(self, other: Miller, raise_error: bool = False) -> bool: + def _compatible_with(self, other: Self, raise_error: bool = False) -> bool: """Whether ``self`` and ``other`` are the same (the same crystal lattice and symmetry) with vectors in the same space. @@ -977,7 +976,7 @@ def _hkil2hkl(hkil: np.ndarray) -> np.ndarray: return hkl -def _check_hkil(hkil: np.ndarray): +def _check_hkil(hkil: np.ndarray) -> None: hkil = np.asarray(hkil) if not np.allclose(np.sum(hkil[..., :3], axis=-1), 0, atol=1e-4): raise ValueError( @@ -1016,7 +1015,7 @@ def _UVTW2uvw(UVTW: np.ndarray, convention: Optional[str] = None) -> np.ndarray: return uvw -def _check_UVTW(UVTW: np.ndarray): +def _check_UVTW(UVTW: np.ndarray) -> None: UVTW = np.asarray(UVTW) if not np.allclose(np.sum(UVTW[..., :3], axis=-1), 0, atol=1e-4): raise ValueError( From 0c023ecc6f4637ce9317fd42487eef43c7f8947a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 22:22:08 +0200 Subject: [PATCH 5/8] Add simple test for Vector3d.get_nearest() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/tests/test_vector3d.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/orix/tests/test_vector3d.py b/orix/tests/test_vector3d.py index 3f628822..7ed4c386 100644 --- a/orix/tests/test_vector3d.py +++ b/orix/tests/test_vector3d.py @@ -460,6 +460,16 @@ def test_zero_perpendicular(): _ = Vector3d.zero((1,)).perpendicular +def test_get_nearest(): + v_ref = Vector3d.zvector() + v = Vector3d([[0, 0, 0.9], [0, 0, 0.8], [0, 0, 1.1]]) + v_nearest = v_ref.get_nearest(v) + assert np.allclose(v_nearest.data, [0, 0, 0.9]) + + with pytest.raises(AttributeError, match="`get_nearest` only works for "): + v.get_nearest(v_ref) + + class TestSpareNotImplemented: def test_radd_notimplemented(self, vector): with pytest.raises(TypeError): From b7e873b2b4a86175a4bee7ea023ad25d28d730ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Mon, 13 May 2024 22:22:24 +0200 Subject: [PATCH 6/8] Replace np.float64(rotation.a) with rotation.a.astype(np.float64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/vector/neo_euler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orix/vector/neo_euler.py b/orix/vector/neo_euler.py index ea822af1..6bb46f9c 100644 --- a/orix/vector/neo_euler.py +++ b/orix/vector/neo_euler.py @@ -140,7 +140,7 @@ def from_rotation(cls, rotation: "Rotation") -> Rodrigues: -------- Quaternion.to_rodrigues """ - a = np.float64(rotation.a) + a = rotation.a.astype(np.float64) with np.errstate(divide="ignore", invalid="ignore"): data = np.stack((rotation.b / a, rotation.c / a, rotation.d / a), axis=-1) data[np.isnan(data)] = 0 From e616f9a39757ff7242b48d5dc4ebb6b32bb1050d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Tue, 14 May 2024 20:32:58 +0200 Subject: [PATCH 7/8] Remove deprecated from_neo_euler() methods and convention parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- CHANGELOG.rst | 4 ++ orix/quaternion/orientation.py | 33 +-------- orix/quaternion/quaternion.py | 40 +---------- orix/quaternion/rotation.py | 3 - orix/tests/quaternion/test_orientation.py | 73 +------------------ orix/tests/quaternion/test_quaternion.py | 85 ++--------------------- orix/vector/neo_euler.py | 5 +- 7 files changed, 18 insertions(+), 225 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bf9b41a8..75b13d7a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,10 @@ Changed Removed ------- +- Removed deprecated ``from_neo_euler()`` method for ``Quaternion`` and its subclasses. +- Removed deprecated argument ``convention`` in ``from_euler()`` and ``to_euler()`` + methods for ``Quaternion`` and its subclasses. Use ``direction`` instead. Passing + ``convention`` will now raise an error. Deprecated ---------- diff --git a/orix/quaternion/orientation.py b/orix/quaternion/orientation.py index 215b090d..d654f3d5 100644 --- a/orix/quaternion/orientation.py +++ b/orix/quaternion/orientation.py @@ -29,11 +29,10 @@ import numpy as np from scipy.spatial.transform import Rotation as SciPyRotation -from orix._util import deprecated from orix.quaternion.misorientation import Misorientation from orix.quaternion.rotation import Rotation from orix.quaternion.symmetry import C1, Symmetry, _get_unique_symmetry_elements -from orix.vector import Miller, NeoEuler, Vector3d +from orix.vector import Miller, Vector3d class Orientation(Misorientation): @@ -107,7 +106,6 @@ def __sub__(self, other: Orientation) -> Misorientation: # ------------------------ Class methods ------------------------- # - # TODO: Remove use of **kwargs in 1.0 @classmethod def from_euler( cls, @@ -115,7 +113,6 @@ def from_euler( symmetry: Optional[Symmetry] = None, direction: str = "lab2crystal", degrees: bool = False, - **kwargs, ) -> Orientation: """Create orientations from sets of Euler angles :cite:`rowenhorst2015consistent`. @@ -141,7 +138,7 @@ def from_euler( O Orientations. """ - O = super().from_euler(euler, direction=direction, degrees=degrees, **kwargs) + O = super().from_euler(euler, direction=direction, degrees=degrees) if symmetry: O.symmetry = symmetry return O @@ -261,32 +258,6 @@ def from_matrix( O.symmetry = symmetry return O - # TODO: Remove before 0.13.0 - @classmethod - @deprecated(since="0.12", removal="0.13", alternative="from_axes_angles") - def from_neo_euler( - cls, neo_euler: NeoEuler, symmetry: Optional[Symmetry] = None - ) -> Orientation: - """Create orientations from a neo-euler (vector) representation. - - Parameters - ---------- - neo_euler - Vector parametrization of orientation(s). - symmetry - Symmetry of orientation(s). If not given (default), no - symmetry is set. - - Returns - ------- - O - Orientations. - """ - O = super().from_neo_euler(neo_euler) - if symmetry: - O.symmetry = symmetry - return O - @classmethod def from_axes_angles( cls, diff --git a/orix/quaternion/quaternion.py b/orix/quaternion/quaternion.py index e7fdf5e2..5b77a39c 100644 --- a/orix/quaternion/quaternion.py +++ b/orix/quaternion/quaternion.py @@ -28,13 +28,9 @@ from scipy.spatial.transform import Rotation as SciPyRotation from orix._base import Object3d -from orix._util import deprecated, deprecated_argument from orix.quaternion import _conversions from orix.vector import AxAngle, Homochoric, Miller, Rodrigues, Vector3d -# Used to round values below 1e-16 to zero -_FLOAT_EPS = np.finfo(float).eps - class Quaternion(Object3d): r"""Quaternions. @@ -259,31 +255,6 @@ def __eq__(self, other: Union[Any, Quaternion]) -> bool: # ------------------------ Class methods ------------------------- # - # TODO: Remove before 0.13.0 - @classmethod - @deprecated(since="0.12", removal="0.13", alternative="from_axes_angles") - def from_neo_euler(cls, neo_euler: "NeoEuler") -> Quaternion: - """Create unit quaternion(s) from a neo-euler (vector) - representation. - - Parameters - ---------- - neo_euler - Vector parametrization of quaternions. - - Returns - ------- - Q - Unit quaternion(s). - """ - s = np.sin(neo_euler.angle / 2) - a = np.cos(neo_euler.angle / 2) - b = s * neo_euler.axis.x - c = s * neo_euler.axis.y - d = s * neo_euler.axis.z - Q = cls(np.stack([a, b, c, d], axis=-1)).unit - return Q - @classmethod def from_axes_angles( cls, @@ -485,15 +456,12 @@ def from_rodrigues( return Q - # TODO: Remove decorator, **kwargs, and use of "convention" in 0.13 @classmethod - @deprecated_argument("convention", "0.9", "0.13", "direction") def from_euler( cls, euler: Union[np.ndarray, tuple, list], direction: str = "lab2crystal", degrees: bool = False, - **kwargs, ) -> Quaternion: """Create unit quaternions from Euler angle sets :cite:`rowenhorst2015consistent`. @@ -517,9 +485,7 @@ def from_euler( Unit quaternions. """ direction = direction.lower() - if direction == "mtex" or ( - "convention" in kwargs and kwargs["convention"] == "mtex" - ): + if direction == "mtex": # MTEX' rotations are transformations from the crystal to # the lab reference frames. See # https://mtex-toolbox.github.io/MTEXvsBungeConvention.html @@ -804,9 +770,7 @@ def identity(cls, shape: Union[int, tuple] = (1,)) -> Quaternion: # ---------------------- All "to_*" methods- --------------------- # - # TODO: Remove decorator and **kwargs in 0.13 - @deprecated_argument("convention", since="0.9", removal="0.13") - def to_euler(self, degrees: bool = False, **kwargs) -> np.ndarray: + def to_euler(self, degrees: bool = False) -> np.ndarray: r"""Return the unit quaternions as Euler angles in the Bunge convention :cite:`rowenhorst2015consistent`. diff --git a/orix/quaternion/rotation.py b/orix/quaternion/rotation.py index de3f7f2e..3042d3e5 100644 --- a/orix/quaternion/rotation.py +++ b/orix/quaternion/rotation.py @@ -28,9 +28,6 @@ from orix.quaternion import Quaternion from orix.vector import Vector3d -# Used to round values below 1e-16 to zero -_FLOAT_EPS = np.finfo(float).eps - class Rotation(Quaternion): r"""Rotations of coordinate systems, leaving objects in place. diff --git a/orix/tests/quaternion/test_orientation.py b/orix/tests/quaternion/test_orientation.py index cefaf8f0..2a87982b 100644 --- a/orix/tests/quaternion/test_orientation.py +++ b/orix/tests/quaternion/test_orientation.py @@ -16,8 +16,6 @@ # You should have received a copy of the GNU General Public License # along with orix. If not, see . -import warnings - from diffpy.structure import Lattice, Structure import matplotlib.pyplot as plt import numpy as np @@ -43,7 +41,7 @@ _groups, _proper_groups, ) -from orix.vector import AxAngle, Miller, Vector3d +from orix.vector import Miller, Vector3d # isort: on # fmt: on @@ -522,22 +520,7 @@ def test_from_align_vectors(self): ): _ = Orientation.from_align_vectors(a, b) - def test_from_neo_euler_symmetry(self): - v = AxAngle.from_axes_angles(axes=Vector3d.zvector(), angles=np.pi / 2) - with pytest.warns(np.VisibleDeprecationWarning): - o1 = Orientation.from_neo_euler(v) - assert np.allclose(o1.data, [0.7071, 0, 0, 0.7071]) - assert o1.symmetry.name == "1" - with pytest.warns(np.VisibleDeprecationWarning): - o2 = Orientation.from_neo_euler(v, symmetry=Oh) - o2 = o2.map_into_symmetry_reduced_zone() - assert np.allclose(o2.data, [-1, 0, 0, 0]) - assert o2.symmetry.name == "m-3m" - o3 = Orientation(o1.data, symmetry=Oh) - o3 = o3.map_into_symmetry_reduced_zone() - assert np.allclose(o3.data, o2.data) - - def test_from_axes_angles(self, rotations): + def test_from_axes_angles(self): axis = Vector3d.xvector() - Vector3d.yvector() angle = np.pi / 2 o1 = Orientation.from_axes_angles(axis, angle, Oh) @@ -587,58 +570,6 @@ def test_from_scipy_rotation(self): with pytest.raises(TypeError, match="Value must be an instance of"): _ = Orientation.from_scipy_rotation(r_scipy, (Oh, Oh)) - # TODO: Remove in 0.13 - def test_from_euler_warns(self): - """Orientation.from_euler() warns only once when "convention" - argument is passed. - """ - euler = np.random.rand(10, 3) - - with warnings.catch_warnings(): - warnings.filterwarnings("error") - _ = Orientation.from_euler(euler) - - msg = ( - r"Argument `convention` is deprecated and will be removed in version 0.13. " - r"To avoid this warning, please do not use `convention`. " - r"Use `direction` instead. See the documentation of `from_euler\(\)` for " - "more details." - ) - with pytest.warns(np.VisibleDeprecationWarning, match=msg) as record2: - _ = Orientation.from_euler(euler, convention="whatever") - assert len(record2) == 1 - - # TODO: Remove in 0.13 - def test_from_euler_convention_mtex(self): - """Passing convention="mtex" to Orientation.from_euler() works - but warns once. - """ - euler = np.random.rand(10, 3) - ori1 = Orientation.from_euler(euler, direction="crystal2lab") - with pytest.warns(np.VisibleDeprecationWarning, match=r"Argument `convention`"): - ori2 = Orientation.from_euler(euler, convention="mtex") - assert np.allclose(ori1.data, ori2.data) - - # TODO: Remove in 0.13 - def test_to_euler_convention_warns(self): - """Orientation.to_euler() warns only once when "convention" - argument is passed. - """ - ori1 = Orientation.from_euler(np.random.rand(10, 3)) - - with warnings.catch_warnings(): - warnings.filterwarnings("error") - ori2 = ori1.to_euler() - - msg = ( - r"Argument `convention` is deprecated and will be removed in version 0.13. " - r"To avoid this warning, please do not use `convention`. " - r"See the documentation of `to_euler\(\)` for more details." - ) - with pytest.warns(np.VisibleDeprecationWarning, match=msg): - ori3 = ori1.to_euler(convention="whatever") - assert np.allclose(ori2, ori3) - class TestOrientation: @pytest.mark.parametrize("symmetry", [C1, C2, C3, C4, D2, D3, D6, T, O, Oh]) diff --git a/orix/tests/quaternion/test_quaternion.py b/orix/tests/quaternion/test_quaternion.py index bc69ca94..e3959164 100644 --- a/orix/tests/quaternion/test_quaternion.py +++ b/orix/tests/quaternion/test_quaternion.py @@ -16,8 +16,6 @@ # You should have received a copy of the GNU General Public License # along with orix. If not, see . -import warnings - import dask.array as da from diffpy.structure.spacegroups import sg225 import numpy as np @@ -25,7 +23,7 @@ from orix._base import DimensionError from orix.quaternion import Quaternion -from orix.vector import AxAngle, Homochoric, Rodrigues, Vector3d +from orix.vector import AxAngle, Homochoric, Vector3d @pytest.fixture( @@ -345,9 +343,6 @@ def test_to_from_euler(self, eu): eu4 = Quaternion.from_euler(eu).to_euler(degrees=True) assert np.allclose(np.rad2deg(eu), eu4) - def test_mtex(self, eu): - _ = Quaternion.from_euler(eu, direction="mtex") - def test_direction_values(self, eu): q_mtex = Quaternion.from_euler(eu, direction="mtex") q_c2l = Quaternion.from_euler(eu, direction="crystal2lab") @@ -357,9 +352,6 @@ def test_direction_values(self, eu): assert np.allclose(q_mtex.data, q_c2l.data) assert np.allclose((q_l2c * q_c2l).data, [1, 0, 0, 0]) - def test_direction_kwarg(self, eu): - _ = Quaternion.from_euler(eu) - def test_direction_kwarg_dumb(self, eu): with pytest.raises(ValueError, match="The chosen direction is not one of "): _ = Quaternion.from_euler(eu, direction="dumb_direction") @@ -376,56 +368,6 @@ def test_passing_degrees_warns(self): q = Quaternion.from_euler([90, 0, 0]) assert np.allclose(q.data, [0.5253, 0, 0, -0.8509], atol=1e-4) - # TODO: Remove in 0.13 - def test_from_euler_warns(self, eu): - """Quaternion.from_euler() warns only when "convention" argument - is passed. - """ - # No warning is raised - with warnings.catch_warnings(): - warnings.simplefilter("error") - _ = Quaternion.from_euler(eu) - - msg = ( - r"Argument `convention` is deprecated and will be removed in version 0.13. " - r"To avoid this warning, please do not use `convention`. " - r"Use `direction` instead. See the documentation of `from_euler\(\)` for " - "more details." - ) - with pytest.warns(np.VisibleDeprecationWarning, match=msg): - _ = Quaternion.from_euler(eu, convention="whatever") - - # TODO: Remove in 0.13 - def test_from_euler_convention_mtex(self, eu): - """Passing convention="mtex" to Quaternion.from_euler() works but - warns. - """ - q1 = Quaternion.from_euler(eu, direction="crystal2lab") - with pytest.warns(np.VisibleDeprecationWarning, match=r"Argument `convention`"): - q2 = Quaternion.from_euler(eu, convention="mtex") - assert np.allclose(q1.data, q2.data) - - # TODO: Remove in 0.13 - def test_to_euler_convention_warns(self, eu): - """Quaternion.to_euler() warns only when "convention" argument is - passed. - """ - q1 = Quaternion.from_euler(eu) - - # No warning is raised - with warnings.catch_warnings(): - warnings.simplefilter("error") - q2 = q1.to_euler() - - msg = ( - r"Argument `convention` is deprecated and will be removed in version 0.13. " - r"To avoid this warning, please do not use `convention`. " - r"See the documentation of `to_euler\(\)` for more details." - ) - with pytest.warns(np.VisibleDeprecationWarning, match=msg): - q3 = q1.to_euler(convention="whatever") - assert np.allclose(q2, q3) - class TestFromToMatrix: def test_to_matrix(self): @@ -516,13 +458,9 @@ def test_from_axes_angles(self, rotations, extra_dim): if extra_dim: rotations = rotations.__class__(rotations.data[..., np.newaxis, :]) ax = AxAngle.from_rotation(rotations) - with pytest.warns(np.VisibleDeprecationWarning): - q2 = Quaternion.from_neo_euler(ax) - q3 = Quaternion.from_axes_angles(ax.axis.data, ax.angle) - assert np.allclose(q2.data, q3.data) - - q4 = Quaternion.from_axes_angles(ax.axis, np.rad2deg(ax.angle), degrees=True) - assert np.allclose(q4.data, q3.data) + Q1 = Quaternion.from_axes_angles(ax.axis.data, ax.angle) + Q2 = Quaternion.from_axes_angles(ax.axis, np.rad2deg(ax.angle), degrees=True) + assert np.allclose(Q1.data, Q2.data) def test_to_axes_angles(self, quaternions_conversions, axis_angle_pairs): ax = Quaternion(quaternions_conversions).to_axes_angles() @@ -556,21 +494,6 @@ def test_from_to_rodrigues(self, quaternions_conversions, rodrigues_vectors): with pytest.raises(ValueError, match="Final dimension of vector array must be"): Quaternion.from_rodrigues([1, 2, 3, 4]) - def test_backwards_consistency(self, quaternions_conversions, rodrigues_vectors): - axes = rodrigues_vectors[..., :3] - angles = rodrigues_vectors[..., 3][..., np.newaxis] - with pytest.warns(RuntimeWarning): - ro = Rodrigues(axes * angles) - - with pytest.warns(np.VisibleDeprecationWarning): - q1 = Quaternion.from_neo_euler(ro) - with pytest.warns(UserWarning, match="Highest angle is greater than 179.999 "): - q2 = Quaternion.from_rodrigues(axes, angles) - - assert np.allclose(q1[2].data, 0) - match_idx = [0, 1, 3, 4, 5, 6, 7, 8, 9] - assert np.allclose(q1[match_idx].data, q2[match_idx].data, atol=1e-4) - def test_from_rodrigues_empty(self): q = Quaternion.from_rodrigues([]) assert q.size == 0 diff --git a/orix/vector/neo_euler.py b/orix/vector/neo_euler.py index 6bb46f9c..7aab52b0 100644 --- a/orix/vector/neo_euler.py +++ b/orix/vector/neo_euler.py @@ -30,12 +30,15 @@ from __future__ import annotations import abc -from typing import Union +from typing import TYPE_CHECKING, Union import numpy as np from orix.vector import Vector3d +if TYPE_CHECKING: # pragma: no cover + from orix.quaternion import Rotation + class NeoEuler(Vector3d, abc.ABC): """Base class for neo-Eulerian vectors.""" From 1a4f34429aac14d7db384abcdf585f04e37b349f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Tue, 14 May 2024 20:35:24 +0200 Subject: [PATCH 8/8] Fix GitHub CI: use only branches-ignore, not in addition to branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6cb5c4ca..f721f637 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,6 @@ name: build on: push: - branches: - - '*' branches-ignore: - 'pre-commit-ci-update-config' pull_request: