Conventions¶
When dealing with polar coordinates, spherical harmonics, rotations, and crystal symmetries, there are a lot of arbitrary choices of how to define angles, normalization, phase factors and so on.
This page tries to make these choices explicit.
Coordinate systems¶
Vectors are represented by numpy-arrays where the last dimension is of length 3 where the last index is in the ordering \(x, y, z\).
Vectors can live in one of two coordinate systems. The lattice coordinate system and the sample
coordinate system. Miller index 3-tuples are not vectors, but can be turned into lattice space vectors by
matrix-multiplying by the reciprocal lattice matrix. Vector-variables are named named \(\mathbf{y}\) or y
to specify that they live in sample-coordinates while variables named \(\mathbf{h}\) or h live in lattice coordinates.
We refer to any voxel-map as a tomogram. Such tomograms have the first 3 dimensions equal to
geometry.volume_shape. The edges of the voxel-map are parallel to the coordinate axes of the sample
coordinate system. with \(x, y, z\) ordering and going from zero to positive.
We rarely make use of explicit real-space coordinates but we consider
the corner of the voxel represented by tomogram[0, 0, 0, ...] to be the origin.
In order to have this coordinate system be equal to the
lab coordinates used by various instruments, the mumott.Geometry obects allows a lot of freedom in
defining various diffractometer geometries. For 2D geometries we still represent the tomograms with 3D numpy-arrays but one dimension is kept length-1. For a
cSAXS-style geometry (beam parallel to z-axis, rotation around y-axis) the 1-length array is the 2nd dimension.
For an PETRA III-ID21.1 style geometry (beam parallel to x-axis, rotation around z-axis) the empty dimension is the
3rd.
Polar coordinates and spherical harmonics¶
While we mostly represent unit vectors in 3-component basis, we sometimes make
use of polar coordinates. The polar angle is called theta or \(\theta\) and goes from the +z pole
(\(\theta=0\)) to the -z pole (\(\theta=\pi\)). The azimuthal angle is called phi or \(\phi\)
and goes from the (+x)-z half plane (\(\phi=0\)) towards the (+y)-z half-plane (\(\phi=\pi/2\)).
The use of \(\theta\) for the polar angle clashes with the common use of \(2\theta\) for the scattering angle. I try to use \(2\theta/2\) whenever the half-scattering angle is needed to avoid confusion.
This choice of coordinates leads to the mapping, from unit-3 vectors to polar coordinates:
and
The second mapping should be implemented with some care:
theta = np.arctan2(np.sqrt(vectors[..., 0]**2 + vectors[..., 1]**2), vectors[..., 2])
phi = np.arctan2(vectors[..., 1], vectors[..., 0])
We use real-spherical harmonics with the notational trick of using neagative m index to denote sine-like harmonics and positive m for cosine-like harmonics. The spherical harmonics used are in these coordinates with normalization convention
and without the Condon-Shotley phase factor.
Rotations, Orientation, Misorientations¶
A transformation of vectors from one coordinate system to another is called a rotation. A transformation from some conventional reference is called an orientation. A rotation from one orientation to another is called a misorientation.
The reference coordinate system used to define orientaitons is implicitly given by a choice of lattice vectors, \(\mathbf{a}\), \(\mathbf{b}\), \(\mathbf{c}\). An explcit choice of coordinates for these defines the lattice coordinate system. One common convention is \(\mathbf{a}||\hat{x}\), \(\mathbf{b}\) in \(\mathrm{Span}(\hat{x}, \hat{y})\) which means the lattice matrix: \(\mathrm{A} = [\mathbf{a}, \mathbf{b}, \mathbf{c}]\) is upper-triangular.
When an \(\mathrm{A}\) is chosen, the reciprocal lattice matrix follows:
\(\mathrm{B}\) allows Miller indicies to be converted into lattice-space vectors: \(\mathbf{h} = \mathrm{B}[h, k, \ell]^{\mathrm{T}}\).
Lattice symmetries are specific rotations that leave the lattice invariant. The explicit form of the symmetry rotations depends on the choice of lattice vectors and the user has to make sure that this choice is self-consisent.
On such choice of consistent lattice vectors and symmetry rotations are implemented in odftt.crystallography and
odftt.texture.point_groups for orthorhombic, hexagonal, and cubic crystals.
Crystal symmetries are applied only to vectors in the lattice coordinate system.
An orientation is defined as the rotation that turns a vector in lattice coordinates (for a given crystallite) into a vector in sample-space coordinates. As different crystalllites have different orientations we can define an orientation field which is the central object of interest in texture analysis.
Lattice symmetries give rise to the concept of symmetry-equivalent orientations. We say that any orientation
is equivalent to the orientaiton \(g_0\) where \(S\) is the set of lattice symmetries. For visualization and statistics, we need to pick a single representative of this equivalence class. Conventionally we pick the one with lower Euler norm, giving rise to the concept of the asymmetric zone, the subspace of orientaion space containing all such representatives.
We say the misorientation \(m'{}_{1\rightarrow2}\) from \(g_1\) to \(g_2\) is the rotation that converts the orientation \(g_1\) into \(g_2\). But since several orientation are equivalent, we only consider the smallest such rotation, that connects two equivalent orientations by finding the minimum:
where \(|\cdot|\) denotes the Euler-norm of a rotation. This gives the minimal rotation to transform \(g_1\) into an equivalent of \(g_2\) applied in sample coordinates. Most commonly, we are rather interested in the misorientation in lattice coordinates. For this we pull the misorientation into the lattice frame of the first crystallite:
Since the lattice coordinate system has symmetries, this gives us an equivalence class of misorientations with the same magnitude. To select a representative, we choose the unique element with the rotation axis in the fundamental zone of \(S\). Eg. in cubic symmetry, the spherical triangle spanned by Miller indicies (001), (101), (111). This space of misorientations is the appropriate for doing statistics eg. to determine twin-laws. While it is not obvious, and I will not attempt to prove it, the misorientation determined this way does not depend on the order of the two orientations.
Representation of rotations¶
As often as posisble, rotations are represented by scipy.spatial.transform.Rotation objects. This package is used so
often that we conventionally import it under the alias R. For equaitons, where present, orientations are written as \(g\)
misorientations as \(m\) (unfortunately clashing with the magnetic index of Spherical Harmonics) and other rotations,
such as the tomographic rotation of the sample, with \(\mathrm{R}\).
When R doesn’t cut it, mainly due to it’s lack of multi-dimensional arrays. We make heavy use of Rodriguez vectors using
the R.from_rotvec() and R.as_rotvec() methods. In those cases, the vector index is last in the array and in (x,y,z)
ordering. Same as other vectors. For example we would have:
main_orientation = R.from_rotvec(
main_orientation_tomogram[x_index, y_index, z_index, :])
)
Generalized spherical harmonics are naturally expressed in Euler-angles. We use the 'zyz' angles, that
can be generated by R.as_euler('zyz'). The three Euler angles are called \(\Psi, \Theta, \Phi\) or (Psi, Theta, Phi).
The names are suggestive of the connection to polar coordinates. Namely that \((\Psi, \Theta, \Phi)\) rotates the z-axis into the point with
polar coordinates \((\theta, \phi) = (\Theta, \Phi)\). \(\Psi\) represents an initial rotation about the z-axis.
We define the generalized spherical harmonics, \(\mathrm{Z}_\ell^{m,n}(g)\), to match our choice of spherical harmonics by the property:
where we are abusing notation to write the spherical harmonic as a function of a unit-vector rather than of two polar coordinates. With our choice of Euler angles we get the property:
which is the sense in which they generalize the spherical harmonics.
The normalization convention is