Skip to content

Commit

Permalink
Merge pull request pyxem#1126 from viljarjf/pyxem#1124-consistent-mar…
Browse files Browse the repository at this point in the history
…ker-plotting

Consistent marker plotting
  • Loading branch information
CSSFrancis authored Dec 9, 2024
2 parents 6718a9e + 4cfdca5 commit 93d1d8a
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 47 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0

Unreleased
==========
Fixed
-----
- Fixed inconsistency with vector markers' positions when plotting orientation mapping results (#1126)

Added
-----
- Added Examples for general plotting functions focusing on plotting diffraction patterns (#1108)
- Added support for marker plotting for multi-phase orientation mapping results (#1092)
- Cleaned up the Documentation for installation (#1109)
- Added an Example for determining the calibration (#1085)
- Added support for multi-phase orientation mapping markers on polar signals (#1126)

Removed
-------
Expand Down
93 changes: 50 additions & 43 deletions pyxem/signals/indexation_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,14 @@ def vectors_from_orientation_map(
rotation = Rotation.from_euler(
(mirror * rotation, 0, 0), degrees=True, direction="crystal2lab"
)

coordinate_format = vectors.coordinate_format
vectors = ~rotation * vectors.to_miller()
vectors = DiffractingVector(
vectors.phase, xyz=vectors.data.copy(), intensity=intensities
vectors.phase,
xyz=-vectors.data.copy(), # Negating for proper alignment - is this flipping z direction?
intensity=intensities,
)
vectors.coordinate_format = coordinate_format
vectors.original_hkl = hkl

# angle = np.deg2rad(mirror * rotation)
Expand Down Expand Up @@ -979,7 +982,7 @@ def to_markers(
annotation_shift: Sequence[float] = None,
text_kwargs: dict = None,
include_intensity: bool = False,
intesity_scale: float = 1,
intensity_scale: float = 1,
fast: bool = True,
**kwargs,
) -> Sequence[hs.plot.markers.Markers]:
Expand Down Expand Up @@ -1025,15 +1028,16 @@ def to_markers(
all_markers = []
for n in range(n_best):
vectors = self.to_vectors(
n_best_index=n,
return_object=False,
lazy_output=True,
navigation_chunks=navigation_chunks,
return_object=False,
)
color = marker_colors[n % len(marker_colors)]
if include_intensity:
intensity = vectors.map(
vectors_to_intensity,
scale=intesity_scale,
scale=intensity_scale,
inplace=False,
ragged=True,
output_dtype=object,
Expand Down Expand Up @@ -1081,13 +1085,32 @@ def to_markers(
all_markers = compute_markers(all_markers)
return all_markers

@deprecated(
since="0.20.0",
alternative="pyxem.signals.OrientationMap.to_polar_markers",
removal="1.0.0",
)
def to_single_phase_polar_markers(
self,
signal_axes: Sequence[BaseDataAxis],
n_best: int = 1,
marker_colors: str = ("red", "blue", "green", "orange", "purple"),
lazy_output: bool = None,
**kwargs,
) -> Iterator[hs.plot.markers.Markers]:
return self.to_polar_markers(
n_best=n_best,
marker_colors=marker_colors,
lazy_output=lazy_output,
**kwargs,
)

def to_polar_markers(
self,
n_best: int = 1,
marker_colors: str = ("red", "blue", "green", "orange", "purple"),
lazy_output: bool = None,
**kwargs,
) -> Iterator[hs.plot.markers.Markers]:
"""
Convert the orientation map to a set of markers for plotting in polar coordinates.
Expand All @@ -1112,53 +1135,37 @@ def to_single_phase_polar_markers(
An list of markers for each of the n_best solutions
"""
(
r_templates,
theta_templates,
intensities_templates,
) = self.simulation.polar_flatten_simulations(
signal_axes[1].axis, signal_axes[0].axis
)

if lazy_output is None:
lazy_output = self._lazy
if not lazy_output:
navigation_chunks = (5,) * self.axes_manager.navigation_dimension
else:
navigation_chunks = None

def marker_generator_factory(n_best_entry: int, r_axis, theta_axis):
theta_min, theta_max = theta_axis.min(), theta_axis.max()

def marker_generator(entry):
index, _, rotation, mirror = entry[n_best_entry]
index = index.astype(int)
mirror = mirror.astype(int)

r_ind = r_templates[index]
r = r_axis[r_ind]

theta_ind = theta_templates[index]
theta = theta_axis[::mirror][theta_ind] + np.deg2rad(rotation)

# Rotate as per https://github.com/pyxem/pyxem/issues/925
theta += np.pi

# handle wrap-around theta
theta -= theta_min
theta %= theta_max - theta_min
theta += theta_min

mask = r != 0
return np.vstack((theta[mask], r[mask])).T

return marker_generator
def vec2polar(vector):
# Bug with dtype of python float
vector = vector.astype(np.float64)
r = np.linalg.norm(vector[:, :2], axis=1)
theta = np.arctan2(
vector[:, 1],
vector[:, 0],
)
# flip y
theta = -theta
return np.vstack([theta, r]).T

all_markers = []
for n in range(n_best):
color = marker_colors[n % len(marker_colors)]
markers_signal = self.map(
marker_generator_factory(n, signal_axes[1].axis, signal_axes[0].axis),
inplace=False,
ragged=True,

vecs = self.to_vectors(
n_best_index=n,
return_object=False,
lazy_output=True,
navigation_chunks=navigation_chunks,
)
markers_signal = vecs.map(vec2polar, inplace=False, ragged=True)

if "sizes" not in kwargs:
kwargs["sizes"] = 15
markers = hs.plot.markers.Points.from_signal(
Expand Down
61 changes: 57 additions & 4 deletions pyxem/tests/signals/test_indexation_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,22 @@ def test_to_markers_lazy(self, simple_multi_rot_orientation_result):
markers = orientations.to_markers()
assert isinstance(markers[0].kwargs["offsets"], da.Array)

def test_to_markers_polar(self, simple_multi_rot_orientation_result):
def test_to_single_phase_markers_polar(self, simple_multi_rot_orientation_result):
orientations, rotations, s = simple_multi_rot_orientation_result
polar = s.get_azimuthal_integral2d(
npt=100, npt_azim=180, inplace=False, mean=True
)
markers = orientations.to_single_phase_polar_markers(
polar.axes_manager.signal_axes
)
from pyxem.common import VisibleDeprecationWarning

with pytest.warns(VisibleDeprecationWarning):
markers = orientations.to_single_phase_polar_markers(
polar.axes_manager.signal_axes
)
assert isinstance(markers[0], hs.plot.markers.Markers)

def test_to_markers_polar(self, simple_multi_rot_orientation_result):
orientations, rotations, s = simple_multi_rot_orientation_result
markers = orientations.to_polar_markers()
assert isinstance(markers[0], hs.plot.markers.Markers)

def test_to_ipf_markers(self, simple_multi_rot_orientation_result):
Expand Down Expand Up @@ -436,3 +444,48 @@ def test_to_ipf_correlation_heatmap_markers_multi_phase(
):
markers = multi_phase_orientation_result.to_ipf_correlation_heatmap_markers()
assert all(isinstance(m, hs.plot.markers.Markers) for m in markers)

def test_vector_markers_correctness(self):
"""
Check if the markers are plotted correctly by performing orientation mapping
on a non-centrosymmetric signal, where only one quadrant is non-zero,
using a template with only one diffraction spot.
This spot should then be plotted in the correct quadrant.
"""
from pyxem.signals import Diffraction2D

# Simple signal: 1 in first quadrant, 0 elsewhere
signal = Diffraction2D(np.array([[[[0, 1], [0, 0]]]]))
signal.calibration(center=None)
polar = signal.get_azimuthal_integral2d(npt=10, npt_azim=36)

from diffpy.structure import Lattice, Atom, Structure
from orix.crystal_map import Phase

# Primitive cubic structure, any will do
l = Lattice(5, 5, 5, 90, 90, 90)
a = [Atom("Au", xyz=[0, 0, 0], lattice=l)]
s = Structure(a, l)
p = Phase(space_group=221, structure=s)
gen = SimulationGenerator()
sim = gen.calculate_diffraction2d(p, with_direct_beam=False)

# Set intensities to 0 for all vectors except one
_, _, v = sim.get_simulation(0)
v.intensity[:-1] = 0
v.intensity[-1] = 1

# Perform matching
res = polar.get_orientation(sim)

# Check cartesian
x, y = res.to_markers()[0].kwargs["offsets"][0, 0][-1]
assert x > 0
# When plotting, the y-axis points downwards, but pyxem defines it as upwards.
# Therefore, the first quadrant, as pyxem defines it, has negative y when plotting.
assert y < 0

# Check polar
r, t = res.to_polar_markers()[0].kwargs["offsets"][0, 0][-1]
assert r > 0
assert 0 < t < np.pi / 2

0 comments on commit 93d1d8a

Please sign in to comment.