From 2516e0c0d1934e513a26603be98eaa5b51f5b234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 21:43:42 +0200 Subject: [PATCH 1/8] Add 'packaging' as a dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- doc/user/installation.rst | 1 + pyproject.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/user/installation.rst b/doc/user/installation.rst index 58e26519..1e3c0a2d 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -130,6 +130,7 @@ This is a list of required package dependencies: * :doc:`matplotlib `: Visualization * :doc:`numba `: CPU acceleration * :doc:`numpy `: Handling of N-dimensional arrays +* :doc:`packaging `: Version comparison * :doc:`pooch `: Downloading and caching of datasets * :doc:`scipy `: Optimization algorithms, filtering and more * `tqdm `__: Progressbars diff --git a/pyproject.toml b/pyproject.toml index 9eca0aea..1c246042 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ dependencies = [ "matplotlib >= 3.6.1", "numba", "numpy", + "packaging", "pooch >= 0.13", # TODO: Remove once diffpy.structure >= 3.2.1 "pycifrw", From e0b4ea814331fd396a1db75910704221476b7d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 21:55:26 +0200 Subject: [PATCH 2/8] Make getting space group from diffpy.structure work for >=3.4.0 too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 41 +++++++++++++++++++ orix/crystal_map/_phase.py | 7 ++-- orix/quaternion/symmetry.py | 8 ++-- .../tests/test_crystal_map/test_phase_list.py | 11 ++--- orix/tests/test_io/test_orix_hdf5.py | 6 +-- orix/tests/test_quaternion/test_symmetry.py | 6 +-- 6 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 orix/_utils/_diffpy_structure_utils.py diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py new file mode 100644 index 00000000..be995156 --- /dev/null +++ b/orix/_utils/_diffpy_structure_utils.py @@ -0,0 +1,41 @@ +# +# Copyright 2018-2026 the orix developers +# +# This file is part of orix. +# +# orix is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# orix is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with orix. If not, see . +# + +"""Utilities for interfacing with diffpy.structure.""" + +from typing import Callable + +from diffpy.structure import __version__ +from diffpy.structure.spacegroups import SpaceGroup +from packaging.version import Version + +DIFFPY_STRUCTURE_VERSION = Version(__version__) + +# TODO: Remove these checks (and most likely this whole file) once +# 3.4.0 is the minimal supported version +if Version(__version__) >= Version("3.4.0"): + from diffpy.structure.spacegroups import get_space_group +else: + from diffpy.structure.spacegroups import GetSpaceGroup as get_space_group + +get_space_group: Callable[[str | int], SpaceGroup] + +__all__ = [ + "get_space_group", +] diff --git a/orix/crystal_map/_phase.py b/orix/crystal_map/_phase.py index 7ac984ed..3221b390 100644 --- a/orix/crystal_map/_phase.py +++ b/orix/crystal_map/_phase.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -27,11 +27,12 @@ from diffpy.structure import Lattice, Structure from diffpy.structure.parsers import p_cif -from diffpy.structure.spacegroups import GetSpaceGroup, SpaceGroup +from diffpy.structure.spacegroups import SpaceGroup from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit import matplotlib.colors as mcolors import numpy as np +from orix._utils._diffpy_structure_utils import get_space_group from orix.plot._util.color import get_matplotlib_color from orix.quaternion.symmetry import ( _EDAX_POINT_GROUP_ALIASES, @@ -207,7 +208,7 @@ def space_group(self) -> SpaceGroup | None: def space_group(self, value: int | SpaceGroup | None) -> None: """Set the space group.""" if isinstance(value, int): - value = GetSpaceGroup(value) + value = get_space_group(value) if not isinstance(value, SpaceGroup) and value is not None: raise ValueError( f"{value!r} must be of type {SpaceGroup}, an integer 1-230, or None" diff --git a/orix/quaternion/symmetry.py b/orix/quaternion/symmetry.py index 6bad5242..e17bb90a 100644 --- a/orix/quaternion/symmetry.py +++ b/orix/quaternion/symmetry.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -21,10 +21,10 @@ from typing import TYPE_CHECKING, Literal -from diffpy.structure.spacegroups import GetSpaceGroup import matplotlib.figure as mfigure import numpy as np +from orix._utils._diffpy_structure_utils import get_space_group from orix.quaternion.rotation import Rotation from orix.vector.vector3d import Vector3d @@ -815,8 +815,8 @@ def get_point_group(space_group_number: int, proper: bool = False) -> Symmetry: >>> pgO.name '432' """ - spg = GetSpaceGroup(space_group_number) - pgn = spg.point_group_name + spg = get_space_group(space_group_number) + pgn: str = spg.point_group_name if proper: return spacegroup2pointgroup_dict[pgn]["proper"] else: diff --git a/orix/tests/test_crystal_map/test_phase_list.py b/orix/tests/test_crystal_map/test_phase_list.py index 89eb2390..d5970c76 100644 --- a/orix/tests/test_crystal_map/test_phase_list.py +++ b/orix/tests/test_crystal_map/test_phase_list.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -18,10 +18,10 @@ # from diffpy.structure import Lattice, Structure -from diffpy.structure.spacegroups import GetSpaceGroup import numpy as np import pytest +from orix._utils._diffpy_structure_utils import get_space_group from orix.crystal_map import Phase, PhaseList @@ -311,7 +311,7 @@ def test_add_phase_in_empty_phaselist(self): pl.add(Phase(name, space_group=sg_no)) assert pl.ids == [0] assert pl.names == [name] - assert pl.space_groups == [GetSpaceGroup(sg_no)] + assert pl.space_groups == [get_space_group(sg_no)] assert pl.structures == [Structure()] def test_add_list_phases_to_phaselist(self): @@ -329,7 +329,8 @@ def test_add_list_phases_to_phaselist(self): pl.add([Phase(name=n, space_group=i) for n, i in zip(new_names, new_sg_no)]) assert pl.names == names + new_names assert pl.space_groups == ( - [GetSpaceGroup(i) for i in sg_no] + [GetSpaceGroup(i) for i in new_sg_no] + [get_space_group(i) for i in sg_no] + + [get_space_group(i) for i in new_sg_no] ) assert pl.colors == colors + ["tab:green", "tab:red"] @@ -349,7 +350,7 @@ def test_add_phaselist_to_phaselist(self): pl1.add(pl2) assert pl1.names == names + names2 assert pl1.space_groups == ( - [GetSpaceGroup(i) for i in sg_no] + [GetSpaceGroup(i) for i in sg_no2] + [get_space_group(i) for i in sg_no] + [get_space_group(i) for i in sg_no2] ) assert pl1.ids == [0, 1, 2, 3] diff --git a/orix/tests/test_io/test_orix_hdf5.py b/orix/tests/test_io/test_orix_hdf5.py index a2ce806a..cb0f53f7 100644 --- a/orix/tests/test_io/test_orix_hdf5.py +++ b/orix/tests/test_io/test_orix_hdf5.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -17,12 +17,12 @@ # along with orix. If not, see . # -from diffpy.structure.spacegroups import GetSpaceGroup from h5py import File import numpy as np import pytest from orix import __version__ as orix_version +from orix._utils._diffpy_structure_utils import get_space_group from orix.crystal_map import CrystalMap, Phase import orix.io as oio from orix.io.plugins.orix_hdf5 import ( @@ -125,7 +125,7 @@ def test_phase2dict_spacegroup(self): phase_dict1 = phase2dict(phase) assert phase_dict1["space_group"] == sg100 - sg200 = GetSpaceGroup(200) + sg200 = get_space_group(200) phase.space_group = sg200 phase_dict2 = phase2dict(phase) assert phase_dict2["space_group"] == sg200.number diff --git a/orix/tests/test_quaternion/test_symmetry.py b/orix/tests/test_quaternion/test_symmetry.py index d27a2096..a79eec6d 100644 --- a/orix/tests/test_quaternion/test_symmetry.py +++ b/orix/tests/test_quaternion/test_symmetry.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -19,11 +19,11 @@ from copy import deepcopy -from diffpy.structure.spacegroups import GetSpaceGroup from matplotlib import pyplot as plt import numpy as np import pytest +from orix._utils._diffpy_structure_utils import get_space_group from orix.quaternion import Rotation, Symmetry, get_point_group # fmt: off @@ -444,7 +444,7 @@ def test_get_point_group(): proper_pg = get_point_group(sg_number, proper=True) assert proper_pg in [C1, C2, C3, C4, C6, D2, D3, D4, D6, O, T] - sg = GetSpaceGroup(sg_number) + sg = get_space_group(sg_number) pg = get_point_group(sg_number, proper=False) assert proper_pg == spacegroup2pointgroup_dict[sg.point_group_name]["proper"] assert pg == spacegroup2pointgroup_dict[sg.point_group_name]["improper"] From 777aab3425bf22511141a378cbfad91e8abc129e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:03:27 +0200 Subject: [PATCH 3/8] Make updating structure lattice work for diffpy.structure >= 3.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 13 ++++++++++++- orix/crystal_map/_phase.py | 8 +++++--- orix/tests/test_crystal_map/test_phase.py | 7 ++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py index be995156..2d7cb6b5 100644 --- a/orix/_utils/_diffpy_structure_utils.py +++ b/orix/_utils/_diffpy_structure_utils.py @@ -22,20 +22,31 @@ from typing import Callable from diffpy.structure import __version__ +from diffpy.structure.lattice import Lattice from diffpy.structure.spacegroups import SpaceGroup +from diffpy.structure.structure import Structure from packaging.version import Version DIFFPY_STRUCTURE_VERSION = Version(__version__) # TODO: Remove these checks (and most likely this whole file) once # 3.4.0 is the minimal supported version -if Version(__version__) >= Version("3.4.0"): +if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): from diffpy.structure.spacegroups import get_space_group else: from diffpy.structure.spacegroups import GetSpaceGroup as get_space_group + +def place_in_lattice(structure: Structure, lattice: Lattice) -> Structure: + if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): + return structure.place_in_lattice(lattice) + else: + return structure.placeInLattice(lattice) + + get_space_group: Callable[[str | int], SpaceGroup] __all__ = [ "get_space_group", + "place_in_lattice", ] diff --git a/orix/crystal_map/_phase.py b/orix/crystal_map/_phase.py index 3221b390..7857ac60 100644 --- a/orix/crystal_map/_phase.py +++ b/orix/crystal_map/_phase.py @@ -32,7 +32,7 @@ import matplotlib.colors as mcolors import numpy as np -from orix._utils._diffpy_structure_utils import get_space_group +from orix._utils._diffpy_structure_utils import get_space_group, place_in_lattice from orix.plot._util.color import get_matplotlib_color from orix.quaternion.symmetry import ( _EDAX_POINT_GROUP_ALIASES, @@ -143,7 +143,7 @@ def structure(self, value: Structure) -> None: new_value = value.copy() # Ensure atom positions are expressed in the new basis - new_value.placeInLattice(Lattice(base=new_matrix)) + new_value = place_in_lattice(new_value, Lattice(base=new_matrix)) # Store old lattice for expand_asymmetric_unit self._diffpy_lattice = old_matrix @@ -402,7 +402,9 @@ def expand_asymmetric_unit(self) -> Phase: # Ensure atom positions are expressed in diffpy's convention diffpy_structure = self.structure.copy() - diffpy_structure.placeInLattice(Lattice(base=self._diffpy_lattice)) + diffpy_structure = place_in_lattice( + diffpy_structure, Lattice(base=self._diffpy_lattice) + ) xyz = diffpy_structure.xyz diffpy_structure.clear() diff --git a/orix/tests/test_crystal_map/test_phase.py b/orix/tests/test_crystal_map/test_phase.py index fa841b73..7e86fc83 100644 --- a/orix/tests/test_crystal_map/test_phase.py +++ b/orix/tests/test_crystal_map/test_phase.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -21,6 +21,7 @@ import numpy as np import pytest +from orix._utils._diffpy_structure_utils import place_in_lattice from orix.crystal_map import Phase from orix.crystal_map._phase import default_lattice, new_structure_matrix_from_alignment from orix.quaternion.symmetry import O, Symmetry @@ -563,7 +564,7 @@ def test_expand_asymmetric_unit( # Check atom positions in ORIGINAL lattice alignment # Doing the check in orix's alignment makes independently computing expected sites difficult s = exp.structure.copy() - s.placeInLattice(Lattice(base=phase._diffpy_lattice)) + s = place_in_lattice(s, Lattice(base=phase._diffpy_lattice)) # Use set to avoid having to ensure the order is the same assert set(tuple(xyz.round(8).tolist()) for xyz in s.xyz) == set( expected_atom_positions @@ -574,7 +575,7 @@ def test_expand_asymmetric_unit( assert np.array_equal(base, exp2.structure.lattice.base) assert len(exp2.structure) == len(expected_atom_positions) s = exp2.structure.copy() - s.placeInLattice(Lattice(base=phase._diffpy_lattice)) + s = place_in_lattice(s, Lattice(base=phase._diffpy_lattice)) assert set(tuple(xyz.round(8).tolist()) for xyz in s.xyz) == set( expected_atom_positions ) From d316a1b3b50085de3c4716d1eab71470a8394f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:12:05 +0200 Subject: [PATCH 4/8] Make getting lattice parameters work for diffpy.structure >= 3.4 without warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 8 ++++++ orix/crystal_map/_phase.py | 8 ++++-- orix/io/plugins/ang.py | 3 ++- orix/io/plugins/orix_hdf5.py | 5 ++-- orix/tests/test_crystal_map/test_phase.py | 14 +++++----- orix/tests/test_io/test_bruker_h5ebsd.py | 5 ++-- orix/tests/test_io/test_ctf.py | 32 ++++++++++++++++++----- orix/tests/test_io/test_orix_hdf5.py | 10 ++++--- orix/tests/test_vector3d/test_miller.py | 3 ++- orix/vector/miller.py | 5 ++-- 10 files changed, 66 insertions(+), 27 deletions(-) diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py index 2d7cb6b5..578898d5 100644 --- a/orix/_utils/_diffpy_structure_utils.py +++ b/orix/_utils/_diffpy_structure_utils.py @@ -31,6 +31,7 @@ # TODO: Remove these checks (and most likely this whole file) once # 3.4.0 is the minimal supported version + if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): from diffpy.structure.spacegroups import get_space_group else: @@ -44,6 +45,13 @@ def place_in_lattice(structure: Structure, lattice: Lattice) -> Structure: return structure.placeInLattice(lattice) +def get_cell_parms(lattice: Lattice) -> tuple[float, float, float, float, float, float]: + if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): + return lattice.cell_parms() + else: + return lattice.abcABG() + + get_space_group: Callable[[str | int], SpaceGroup] __all__ = [ diff --git a/orix/crystal_map/_phase.py b/orix/crystal_map/_phase.py index 7857ac60..f605cdb0 100644 --- a/orix/crystal_map/_phase.py +++ b/orix/crystal_map/_phase.py @@ -32,7 +32,11 @@ import matplotlib.colors as mcolors import numpy as np -from orix._utils._diffpy_structure_utils import get_space_group, place_in_lattice +from orix._utils._diffpy_structure_utils import ( + get_cell_parms, + get_space_group, + place_in_lattice, +) from orix.plot._util.color import get_matplotlib_color from orix.quaternion.symmetry import ( _EDAX_POINT_GROUP_ALIASES, @@ -266,7 +270,7 @@ def is_hexagonal(self) -> bool: """Return whether the crystal structure is hexagonal/trigonal or not. """ - return np.allclose(self.structure.lattice.abcABG()[3:], [90, 90, 120]) + return np.allclose(get_cell_parms(self.structure.lattice)[3:], [90, 90, 120]) @property def a_axis(self) -> Miller: diff --git a/orix/io/plugins/ang.py b/orix/io/plugins/ang.py index 409085da..dd72530d 100644 --- a/orix/io/plugins/ang.py +++ b/orix/io/plugins/ang.py @@ -29,6 +29,7 @@ import numpy as np from orix import __version__ +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.crystal_map._phase_list import PhaseList from orix.crystal_map.crystal_map import CrystalMap, create_coordinate_arrays from orix.quaternion.rotation import Rotation @@ -618,7 +619,7 @@ def _get_header_from_phases(xmap: CrystalMap) -> str: # Phase IDs are reversed because EDAX TSL OIM Analysis v7.2.0 # assumes a reversed phase order in the header for i, (_, phase) in reversed(list(enumerate(pl))): - lattice_constants = phase.structure.lattice.abcABG() + lattice_constants = get_cell_parms(phase.structure.lattice) lattice_constants = " ".join([f"{float(val):.3f}" for val in lattice_constants]) phase_id = i + 1 phase_name = phase.name diff --git a/orix/io/plugins/orix_hdf5.py b/orix/io/plugins/orix_hdf5.py index ca78873f..db4c4f2d 100644 --- a/orix/io/plugins/orix_hdf5.py +++ b/orix/io/plugins/orix_hdf5.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -28,6 +28,7 @@ from h5py import File, Group import numpy as np +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.crystal_map._phase import Phase from orix.crystal_map._phase_list import PhaseList from orix.crystal_map.crystal_map import CrystalMap @@ -445,7 +446,7 @@ def lattice2dict(lattice: Lattice, dictionary: dict | None = None) -> dict: """ if dictionary is None: dictionary = {} - dictionary["abcABG"] = np.array(lattice.abcABG()) + dictionary["abcABG"] = np.array(get_cell_parms(lattice)) dictionary["baserot"] = lattice.baserot return dictionary diff --git a/orix/tests/test_crystal_map/test_phase.py b/orix/tests/test_crystal_map/test_phase.py index 7e86fc83..f34af162 100644 --- a/orix/tests/test_crystal_map/test_phase.py +++ b/orix/tests/test_crystal_map/test_phase.py @@ -21,7 +21,7 @@ import numpy as np import pytest -from orix._utils._diffpy_structure_utils import place_in_lattice +from orix._utils._diffpy_structure_utils import get_cell_parms, place_in_lattice from orix.crystal_map import Phase from orix.crystal_map._phase import default_lattice, new_structure_matrix_from_alignment from orix.quaternion.symmetry import O, Symmetry @@ -114,7 +114,9 @@ def test_copy_constructor_phase(self): assert p1.structure[0].element == p2.structure[0].element assert tuple(p1.structure[0].xyz) == tuple(p2.structure[0].xyz) assert p1.structure[0] is not p2.structure[0] - assert p1.structure.lattice.abcABG() == p2.structure.lattice.abcABG() + assert get_cell_parms(p1.structure.lattice) == get_cell_parms( + p2.structure.lattice + ) assert p1.structure.lattice is not p2.structure.lattice @pytest.mark.parametrize("name", [None, "al", 1, np.arange(2)]) @@ -273,7 +275,7 @@ def test_structure_matrix(self): lattice = phase.structure.lattice # Lattice parameters are unchanged - assert np.allclose(lattice.abcABG(), [1.7, 1.7, 1.4, 90, 90, 120]) + assert np.allclose(get_cell_parms(lattice), [1.7, 1.7, 1.4, 90, 90, 120]) # Structure matrix has changed internally, but not the input # `Lattice` instance @@ -413,7 +415,7 @@ def test_from_cif(self, cif_file): assert phase.point_group.name == "2/m" assert len(phase.structure) == 22 # Number of atoms lattice = phase.structure.lattice - assert np.allclose(lattice.abcABG(), [15.5, 4.05, 6.74, 90, 105.3, 90]) + assert np.allclose(get_cell_parms(lattice), [15.5, 4.05, 6.74, 90, 105.3, 90]) assert np.allclose( lattice.base, [[15.5, 0, 0], [0, 4.05, 0], [-1.779, 0, 6.501]], atol=1e-3 ) @@ -970,12 +972,12 @@ def test_expand_asymmetric_unit_raise_if_no_point_group(self): def test_default_lattice(self): for S in ["1", "2", "222", "422", "432"]: phase = Phase(point_group=S) - lattice_parameters = phase.structure.lattice.abcABG() + lattice_parameters = get_cell_parms(phase.structure.lattice) assert np.allclose([1, 1, 1, 90, 90, 90], lattice_parameters) for S in ["3", "622"]: phase = Phase(point_group=S) - lattice_parameters = phase.structure.lattice.abcABG() + lattice_parameters = get_cell_parms(phase.structure.lattice) assert np.allclose([1, 1, 1, 90, 90, 120], lattice_parameters) def test_default_lattice_raises(self): diff --git a/orix/tests/test_io/test_bruker_h5ebsd.py b/orix/tests/test_io/test_bruker_h5ebsd.py index c783bbb4..7a32ca6e 100644 --- a/orix/tests/test_io/test_bruker_h5ebsd.py +++ b/orix/tests/test_io/test_bruker_h5ebsd.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -20,6 +20,7 @@ import numpy as np import pytest +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.io import load @@ -89,7 +90,7 @@ def test_load_bruker_h5ebsd( pid = phase_id[-1] assert xmap.phases[pid].space_group.number == 225 assert np.allclose( - xmap.phases[pid].structure.lattice.abcABG()[3:], [90, 90, 90] + get_cell_parms(xmap.phases[pid].structure.lattice)[3:], [90, 90, 90] ) if 0 in phase_id: assert -1 in xmap.phases.ids diff --git a/orix/tests/test_io/test_ctf.py b/orix/tests/test_io/test_ctf.py index 7fbde02e..9535154f 100644 --- a/orix/tests/test_io/test_ctf.py +++ b/orix/tests/test_io/test_ctf.py @@ -1,5 +1,5 @@ # -# Copyright 2018-2025 the orix developers +# Copyright 2018-2026 the orix developers # # This file is part of orix. # @@ -17,11 +17,12 @@ # along with orix. If not, see . # -from diffpy.structure import Atom, Lattice, Structure +from diffpy.structure import Lattice, Structure import numpy as np import pytest from orix import io +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.crystal_map import PhaseList @@ -118,7 +119,8 @@ def test_load_ctf_oxford( assert phase.name == phase_test.name assert phase.space_group.number == phase_test.space_group.number assert np.allclose( - phase.structure.lattice.abcABG(), phase_test.structure.lattice.abcABG() + get_cell_parms(phase.structure.lattice), + get_cell_parms(phase_test.structure.lattice), ) @pytest.mark.parametrize( @@ -191,7 +193,14 @@ def test_load_ctf_bruker(self, ctf_bruker, map_shape, R_example): phase = xmap.phases[1] assert phase.name == "Gold" assert phase.space_group.number == 225 - assert phase.structure.lattice.abcABG() == (4.079, 4.079, 4.079, 90, 90, 90) + assert get_cell_parms(phase.structure.lattice) == ( + 4.079, + 4.079, + 4.079, + 90, + 90, + 90, + ) @pytest.mark.parametrize( "ctf_astar, map_shape, R_example", @@ -263,7 +272,14 @@ def test_load_ctf_astar(self, ctf_astar, map_shape, R_example): phase = xmap.phases[1] assert phase.name == "_mineral 'Gold' 'Gold'" assert phase.space_group.number == 225 - assert phase.structure.lattice.abcABG() == (4.078, 4.078, 4.078, 90, 90, 90) + assert get_cell_parms(phase.structure.lattice) == ( + 4.078, + 4.078, + 4.078, + 90, + 90, + 90, + ) @pytest.mark.parametrize( "ctf_emsoft, map_shape, step_sizes, R_example", @@ -353,7 +369,8 @@ def test_load_ctf_emsoft( assert phase.name == phase_test.name assert phase.space_group.number == phase_test.space_group.number assert np.allclose( - phase.structure.lattice.abcABG(), phase_test.structure.lattice.abcABG() + get_cell_parms(phase.structure.lattice), + get_cell_parms(phase_test.structure.lattice), ) @pytest.mark.parametrize( @@ -443,5 +460,6 @@ def test_load_ctf_mtex( assert phase.name == phase_test.name assert phase.point_group.name == phase_test.point_group.name assert np.allclose( - phase.structure.lattice.abcABG(), phase_test.structure.lattice.abcABG() + get_cell_parms(phase.structure.lattice), + get_cell_parms(phase_test.structure.lattice), ) diff --git a/orix/tests/test_io/test_orix_hdf5.py b/orix/tests/test_io/test_orix_hdf5.py index cb0f53f7..03393456 100644 --- a/orix/tests/test_io/test_orix_hdf5.py +++ b/orix/tests/test_io/test_orix_hdf5.py @@ -22,7 +22,7 @@ import pytest from orix import __version__ as orix_version -from orix._utils._diffpy_structure_utils import get_space_group +from orix._utils._diffpy_structure_utils import get_cell_parms, get_space_group from orix.crystal_map import CrystalMap, Phase import orix.io as oio from orix.io.plugins.orix_hdf5 import ( @@ -180,7 +180,9 @@ def test_dict2phase(self, phase_list): assert phase1.color == phase2.color assert phase1.space_group.number == phase2.space_group.number assert phase1.point_group.name == phase2.point_group.name - assert phase1.structure.lattice.abcABG() == phase2.structure.lattice.abcABG() + assert get_cell_parms(phase1.structure.lattice) == get_cell_parms( + phase2.structure.lattice + ) def test_dict2phase_spacegroup(self): """Space group number int or None is properly parsed from a dict.""" @@ -195,7 +197,7 @@ def test_dict2structure(self, phase_list): lattice1 = structure1.lattice lattice2 = structure2.lattice - assert lattice1.abcABG() == lattice2.abcABG() + assert get_cell_parms(lattice1) == get_cell_parms(lattice2) assert np.allclose(lattice1.baserot, lattice2.baserot) assert str(structure1.element) == str(structure2.element) @@ -205,7 +207,7 @@ def test_dict2lattice(self, phase_list): lattice = phase_list[0].structure.lattice lattice2 = dict2lattice(lattice2dict(lattice)) - assert lattice.abcABG() == lattice2.abcABG() + assert get_cell_parms(lattice) == get_cell_parms(lattice2) assert np.allclose(lattice.baserot, lattice2.baserot) def test_dict2atom(self, phase_list): diff --git a/orix/tests/test_vector3d/test_miller.py b/orix/tests/test_vector3d/test_miller.py index bb73bb59..673a5ef3 100644 --- a/orix/tests/test_vector3d/test_miller.py +++ b/orix/tests/test_vector3d/test_miller.py @@ -21,6 +21,7 @@ import numpy as np import pytest +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.crystal_map import Phase from orix.quaternion import Orientation, symmetry from orix.vector import Miller @@ -565,7 +566,7 @@ def test_tetragonal_crystal(self): assert np.allclose(m7.round().hkl, [1, 1, 16]) # Example 1.9: Reciprocal lattice parameters - assert np.allclose(lattice_recip.abcABG(), [2, 2, 1, 90, 90, 90]) + assert np.allclose(get_cell_parms(lattice_recip), [2, 2, 1, 90, 90, 90]) # Example 1.10, 1.11: Cross product of two directions m8 = Miller(uvw=[1, 1, 0], phase=TETRAGONAL_PHASE) diff --git a/orix/vector/miller.py b/orix/vector/miller.py index 1735d8ff..b6a59c54 100644 --- a/orix/vector/miller.py +++ b/orix/vector/miller.py @@ -26,6 +26,7 @@ from diffpy.structure import Lattice import numpy as np +from orix._utils._diffpy_structure_utils import get_cell_parms from orix.vector.vector3d import Vector3d if TYPE_CHECKING: # pragma: no cover @@ -871,8 +872,8 @@ def _compatible_with(self, other: Miller, raise_error: bool = False) -> bool: """ same_symmetry = self.phase.point_group == other.phase.point_group same_lattice = np.allclose( - self.phase.structure.lattice.abcABG(), - other.phase.structure.lattice.abcABG(), + get_cell_parms(self.phase.structure.lattice), + get_cell_parms(other.phase.structure.lattice), ) same_space = self.space == other.space compatible = same_symmetry * same_lattice * same_space From 4c5b869cb17a05dfb2539140a96ea2537694bf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:18:58 +0200 Subject: [PATCH 5/8] Silence warnings from diffpy.structure.loadStructure for >= 3.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 7 ++++++- orix/tests/conftest.py | 4 ++-- orix/tests/test_crystal_map/test_phase.py | 12 ++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py index 578898d5..7dd80391 100644 --- a/orix/_utils/_diffpy_structure_utils.py +++ b/orix/_utils/_diffpy_structure_utils.py @@ -19,7 +19,7 @@ """Utilities for interfacing with diffpy.structure.""" -from typing import Callable +from typing import Any, Callable from diffpy.structure import __version__ from diffpy.structure.lattice import Lattice @@ -33,8 +33,10 @@ # 3.4.0 is the minimal supported version if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): + from diffpy.structure import load_structure from diffpy.structure.spacegroups import get_space_group else: + from diffpy.structure import loadStructure as load_structure from diffpy.structure.spacegroups import GetSpaceGroup as get_space_group @@ -53,8 +55,11 @@ def get_cell_parms(lattice: Lattice) -> tuple[float, float, float, float, float, get_space_group: Callable[[str | int], SpaceGroup] +# Simplified signature for our current use case +load_structure: Callable[[str], Structure] __all__ = [ "get_space_group", + "load_structure", "place_in_lattice", ] diff --git a/orix/tests/conftest.py b/orix/tests/conftest.py index 9aa0b05b..fddd823c 100644 --- a/orix/tests/conftest.py +++ b/orix/tests/conftest.py @@ -26,7 +26,7 @@ from collections import OrderedDict from numbers import Number -from typing import Callable +from typing import Callable, Generator from diffpy.structure import Atom, Lattice, Structure from h5py import File @@ -1088,7 +1088,7 @@ def temp_bruker_h5ebsd_file(tmpdir, request): @pytest.fixture -def cif_file(tmpdir): +def cif_file(tmpdir) -> Generator[str, None, None]: """Actual CIF file of beta double prime phase often seen in Al-Mg-Si alloys. """ diff --git a/orix/tests/test_crystal_map/test_phase.py b/orix/tests/test_crystal_map/test_phase.py index f34af162..80b33efe 100644 --- a/orix/tests/test_crystal_map/test_phase.py +++ b/orix/tests/test_crystal_map/test_phase.py @@ -17,11 +17,15 @@ # along with orix. If not, see . # -from diffpy.structure import Atom, Lattice, Structure, loadStructure +from diffpy.structure import Atom, Lattice, Structure import numpy as np import pytest -from orix._utils._diffpy_structure_utils import get_cell_parms, place_in_lattice +from orix._utils._diffpy_structure_utils import ( + get_cell_parms, + load_structure, + place_in_lattice, +) from orix.crystal_map import Phase from orix.crystal_map._phase import default_lattice, new_structure_matrix_from_alignment from orix.quaternion.symmetry import O, Symmetry @@ -420,9 +424,9 @@ def test_from_cif(self, cif_file): lattice.base, [[15.5, 0, 0], [0, 4.05, 0], [-1.779, 0, 6.501]], atol=1e-3 ) - def test_from_cif_same_structure(self, cif_file): + def test_from_cif_same_structure(self, cif_file: str): phase1 = Phase.from_cif(cif_file) - structure = loadStructure(cif_file) + structure = load_structure(cif_file) phase2 = Phase(structure=structure) assert np.allclose(phase1.structure.lattice.base, phase2.structure.lattice.base) assert np.allclose(phase1.structure.xyz, phase2.structure.xyz) From 7d3b026624edbeb373d254654f06cb89cd8f77ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:27:35 +0200 Subject: [PATCH 6/8] Silence warning from diffpy.structure regarding CIF parsing for >= 3.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 14 +++++++++++++- orix/crystal_map/_phase.py | 7 +++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py index 7dd80391..36e9a310 100644 --- a/orix/_utils/_diffpy_structure_utils.py +++ b/orix/_utils/_diffpy_structure_utils.py @@ -19,10 +19,12 @@ """Utilities for interfacing with diffpy.structure.""" -from typing import Any, Callable +from functools import cache +from typing import Callable from diffpy.structure import __version__ from diffpy.structure.lattice import Lattice +from diffpy.structure.parsers import p_cif from diffpy.structure.spacegroups import SpaceGroup from diffpy.structure.structure import Structure from packaging.version import Version @@ -54,12 +56,22 @@ def get_cell_parms(lattice: Lattice) -> tuple[float, float, float, float, float, return lattice.abcABG() +def get_parser_and_structure_from_cif_file(fname: str) -> tuple[p_cif.P_cif, Structure]: + parser = p_cif.P_cif() + if DIFFPY_STRUCTURE_VERSION >= Version("3.4.0"): + structure = parser.parse_file(fname) + else: + structure = parser.parseFile(fname) + return parser, structure + + get_space_group: Callable[[str | int], SpaceGroup] # Simplified signature for our current use case load_structure: Callable[[str], Structure] __all__ = [ "get_space_group", + "get_parser_and_structure_from_cif_file", "load_structure", "place_in_lattice", ] diff --git a/orix/crystal_map/_phase.py b/orix/crystal_map/_phase.py index f605cdb0..075c29ee 100644 --- a/orix/crystal_map/_phase.py +++ b/orix/crystal_map/_phase.py @@ -26,7 +26,6 @@ import warnings from diffpy.structure import Lattice, Structure -from diffpy.structure.parsers import p_cif from diffpy.structure.spacegroups import SpaceGroup from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit import matplotlib.colors as mcolors @@ -34,6 +33,7 @@ from orix._utils._diffpy_structure_utils import ( get_cell_parms, + get_parser_and_structure_from_cif_file, get_space_group, place_in_lattice, ) @@ -355,14 +355,13 @@ def from_cif(cls, filename: str | Path) -> Phase: file format. """ path = Path(filename) - parser = p_cif.P_cif() - name = path.stem - structure = parser.parseFile(str(path)) + parser, structure = get_parser_and_structure_from_cif_file(str(path)) try: space_group = parser.spacegroup.number except AttributeError: # pragma: no cover space_group = None warnings.warn(f"Could not read space group from CIF file {path!r}") + name = path.stem return cls(name, space_group, structure=structure) def deepcopy(self) -> Phase: From 34609a26f46955d327949fceaa618b498ec0eb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:29:56 +0200 Subject: [PATCH 7/8] Add unreleased section to changelog, mention silencted diffpy.structure warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 647e4f60..b07dd76e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,13 @@ All user facing changes to this project are documented in this file. The format on `Keep a Changelog `__, and this project tries its best to adhere to `Semantic Versioning `__. +Unreleased +========== + +Fixed +----- +- Silenced most warnings from diffpy.structure >= 3.4. + 2026-06-10 - version 0.15.0 =========================== From f2ad1cd4acb1b4389aca19b5f1bee2c9e53d9c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akon=20Wiik=20A=CC=8Anes?= Date: Wed, 10 Jun 2026 22:32:19 +0200 Subject: [PATCH 8/8] Silence warning from test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/_utils/_diffpy_structure_utils.py | 1 - pyproject.toml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/orix/_utils/_diffpy_structure_utils.py b/orix/_utils/_diffpy_structure_utils.py index 36e9a310..f0160fe7 100644 --- a/orix/_utils/_diffpy_structure_utils.py +++ b/orix/_utils/_diffpy_structure_utils.py @@ -19,7 +19,6 @@ """Utilities for interfacing with diffpy.structure.""" -from functools import cache from typing import Callable from diffpy.structure import __version__ diff --git a/pyproject.toml b/pyproject.toml index 1c246042..18ca7acf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,6 +108,7 @@ doctest_optionflags = "NORMALIZE_WHITESPACE" filterwarnings = [ "ignore:Deprecated call to `pkg_resources:DeprecationWarning", "ignore:pkg_resources is deprecated as an API:DeprecationWarning", + "ignore:'diffpy.structure.expandPosition':DeprecationWarning:", ] markers = [ "slow: mark test as slow",