Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cartesian crystal reference frame #947

Open
rbjorge opened this issue Aug 14, 2023 · 2 comments
Open

Cartesian crystal reference frame #947

rbjorge opened this issue Aug 14, 2023 · 2 comments

Comments

@rbjorge
Copy link
Contributor

rbjorge commented Aug 14, 2023

Describe the bug

When it comes to choosing the Cartesian crystal reference frame, orix uses one convention, while diffsims uses another (https://orix.readthedocs.io/en/stable/tutorials/crystal_reference_frame.html).
For non-orthogonal crystal structures this can be confusing, especially now that indexation_utils.results_dict_to_crystal_map() creates an orix CrystalMap based on template matching using templates made by diffsims, without changing the Euler angles. When plotting the orientations of the CrystalMap for a hexagonal phase, for example, the blue and green colors are switched.

To Reproduce

To illustrate, using the orientation (0°, 90°, 120°) for a hexagonal phase:

import numpy as np
import diffpy
from diffsims.generators.diffraction_generator import DiffractionGenerator
from orix.quaternion import Rotation
from orix.vector import Vector3d, Miller
from orix.crystal_map import Phase

latt = diffpy.structure.lattice.Lattice(2.46,2.46,6.71,90,90,120)
atoms = [diffpy.structure.atom.Atom(atype='C',xyz=[0.0,0.0,0.25],lattice=latt),
         diffpy.structure.atom.Atom(atype='C',xyz=[0.33333,0.66667,0.25],lattice=latt)]
structure_matrix = diffpy.structure.Structure(atoms=atoms,lattice=latt)
scale = 0.027; half_shape = 64; rec_rad = scale * half_shape
diff_gen = DiffractionGenerator(accelerating_voltage=200, precession_angle=0,
                                scattering_params='xtables',
                                shape_factor_model="linear", minimum_intensity=0.01)
euler = np.array([0, 90, 120])
sim = diff_gen.calculate_ed_data(structure_matrix, reciprocal_radius=rec_rad, 
                                rotation=euler, with_direct_beam=False,
                                max_excitation_error=0.02)
sim.calibration = np.array([scale, scale])
sim.plot(size_factor=30, show_labels=True);

100_za_graphite
We see from the diffraction pattern that this is the $[100]$ (aka. $[2\bar{1}\bar{1}0]$) zone axis.

However, orix interprets (0°, 90°, 120°) as the zone axis $[1\bar{1}0]$ ($[1\bar{1}00]$ in 4-index):

graphite = Phase(point_group="6/mmm", structure=structure_matrix)
rot = Rotation.from_euler(euler, degrees=True)
za_vec = rot * Vector3d.zvector()
za = Miller(xyz=za_vec.data, phase=graphite)
za.coordinate_format="uvw"
za.round()

Out:
Miller (1,), point group 6/mmm, uvw
[[ 1. -1.  0.]]

My work-around for now is to plot the orientation maps in MTEX. I suppose there are in principle at least three possible solutions: change the convention in diffsims inherited from diffpy (as orix does now), change the orix convention, or convert the orientations when making the CrystalMap object. Personally I prefer the first option, although that would make it a diffsims issue..

@hakonanes
Copy link
Member

Thank you for the detailed report, @rbjorge.

I think the best option is to allow different alignments in orix' Phase class. So far, the symmetry elements in orix are hard-coded for a specific alignment (https://github.com/pyxem/orix/blob/develop/orix/quaternion/symmetry.py#L523-L660). We should rather create these on-the-fly based on the desired alignment. Then kikuchipy and pyxem/diffsims (via diffpy.structure) can use different conventions.

Before doing that, though, I'd like to be able to automatically plot symmetry markers for any point group in the stereographic projection. I've started on that in this branch on my fork: https://github.com/hakonanes/orix/tree/plot-symmetry-operations. I don't have time to work on this at the moment. I've added an issue (pyxem/orix#456) to describe what we need.

What do you think, @rbjorge?

@rbjorge
Copy link
Contributor Author

rbjorge commented Aug 15, 2023

I agree that it makes sense to allow different alignments of the Cartesian reference frame in the Phase class, since the orientations can come from different sources, and this flexibility exists in MTEX, for example. That being said, I have to admit I used MTEX for quite some time without understanding that this alignment must be in agreement with the convention chosen when the diffraction patterns were indexed (and not just "this phase is monoclinic, so let's set z // b"). So I think it's good if pyxem's indexation_utils.results_dict_to_crystal_map() selects the right alignment by default.

In the meantime, would it be possible to come up with a code snippet that converts orientations based on the diffpy convention to the orix convention? This could be included in the pyxem conventions notebook.

@hakonanes hakonanes removed this from the v0.16.0 milestone Nov 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants