From 34f19cb9d6791c0156a404d060d9496ec4b16e8b Mon Sep 17 00:00:00 2001 From: aaronkanzer Date: Sat, 24 Oct 2026 07:56:42 -0400 Subject: [PATCH] Fix map data and slicing for crystal maps not starting at zero --- CHANGELOG.rst | 3 +++ orix/crystal_map/crystal_map.py | 10 +++++++++- orix/tests/test_crystal_map/test_crystal_map.py | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1aa57d8e..d7ea2525 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -43,6 +43,9 @@ Fixed multi-dimensional orientations. - Quaternions plotted in a 3D projection (axis-Angle, Rodrigues, homochoric, etc.) will now correctly be transformed using the same algorithms as for rotations. +- ``CrystalMap.get_map_data()`` and slicing a crystal map now work for maps whose + coordinates do not start at zero. Previously, an empty array was returned or a + ``ValueError`` was raised. Deprecated ---------- diff --git a/orix/crystal_map/crystal_map.py b/orix/crystal_map/crystal_map.py index 192b8bfe..c6a84dca 100644 --- a/orix/crystal_map/crystal_map.py +++ b/orix/crystal_map/crystal_map.py @@ -1089,11 +1089,19 @@ def _data_slices_from_coordinates(self, only_is_in_data: bool = True) -> tuple: slices Data slice in each existing direction in (y, x) order. """ + steps = self._step_sizes if only_is_in_data: coordinates = self._coordinates else: coordinates = self._all_coordinates - slices = _data_slices_from_coordinates(coordinates, self._step_sizes) + slices = _data_slices_from_coordinates(coordinates, steps) + # Make slices relative to the first point in the full map, so + # that maps whose coordinates do not start at zero can be + # indexed into arrays of the original map shape + origin = _data_slices_from_coordinates(self._all_coordinates, steps) + slices = tuple( + slice(s.start - o.start, s.stop - o.start) for s, o in zip(slices, origin) + ) return slices def _data_shape_from_coordinates(self, only_is_in_data: bool = True) -> tuple: diff --git a/orix/tests/test_crystal_map/test_crystal_map.py b/orix/tests/test_crystal_map/test_crystal_map.py index 4bb33549..54e595ac 100644 --- a/orix/tests/test_crystal_map/test_crystal_map.py +++ b/orix/tests/test_crystal_map/test_crystal_map.py @@ -1140,6 +1140,22 @@ def test_coordinate_axes(self, crystal_map_input, expected_coordinate_axes): xmap = CrystalMap(**crystal_map_input) assert xmap._coordinate_axes == expected_coordinate_axes + def test_coordinates_not_starting_at_zero(self): + # E.g. a region of interest exported with stage coordinates + d, map_size = create_coordinate_arrays((3, 4), step_sizes=(0.5, 0.5)) + d["x"] = d["x"] + 10 + d["y"] = d["y"] + 3 + xmap = CrystalMap(rotations=Rotation.identity(map_size), **d) + assert xmap.shape == (3, 4) + x = xmap.get_map_data("x") + assert x.shape == (3, 4) + assert np.allclose(x[0], [10, 10.5, 11, 11.5]) + + xmap2 = xmap[1:, 1:] + assert xmap2.shape == (2, 3) + assert np.allclose(xmap2.get_map_data("x")[0], [10.5, 11, 11.5]) + assert np.allclose(xmap2.get_map_data("y")[:, 0], [3.5, 4]) + def test_data_slices_from_coordinates_no_steps(self): d, _ = create_coordinate_arrays((3, 4), step_sizes=(0.1, 0.2)) slices = _data_slices_from_coordinates(d)