-
Notifications
You must be signed in to change notification settings - Fork 27
Description
I think our current precession simulations could be improved a little. Currently we use "max_excitation_error" to eliminate spots from our precessed simulations, but this isn't quiet accurate as it doesn't account for the size of the g vector sensibly.
Case 1 (no approximation):
This finds the average excitation error, but a spot can have an average excitation error greater than max_excitation_error and we would still expect to see it in a pattern as long as somewhere on the circuit it had a sufficiently small excitation error. This is a bug (I think).
Case 2 (approximation):
These spots are eliminated before we even consider that there is precession going on.
Proposed solution:
Working from Equation 10 of [1] which provides the intensity of a spot as a function of:
g-vector (we have this)
precession angle (we have this)
the unprecessed excitation error, which is exactly what we have
the extinction distance (we can use max_excitation_error as a proxy)
(and is currently used in "lorenztian precession)
What Figure 3 (same manuscript) shows is that changing max_excitation_error doesn't change the width of the camel plot significantly. This is likely because we are in the regime (below equation 11) where we have full integration of our spots. We could create two cases (basically by hand) and use them as the eliminations. They would be:
~ numerical_factor * g * phi (precesison regime)
~ The 98th percentile (or similar) of the phi = 0 lorenztian
I would take this opportunity to remove the "manual integration" as I'm not sure this is a particularly good option.
[1] - Specifics of the data processing of precession electron diffraction tomography data and their implementation in the program PETS2.0 - Lukáš Palatinus et al.
Code
As it currently is.
# Identify points intersecting the Ewald sphere within maximum
# excitation error and store the magnitude of their excitation error.
r_sphere = 1 / wavelength
r_spot = np.sqrt(np.sum(np.square(cartesian_coordinates[:, :2]), axis=1))
z_spot = cartesian_coordinates[:, 2]
if self.precession_angle > 0 and not self.approximate_precession:
# We find the average excitation error - this step can be
# quite expensive
excitation_error = _average_excitation_error_precession(
z_spot,
r_spot,
wavelength,
self.precession_angle,
)
else:
z_sphere = -np.sqrt(r_sphere ** 2 - r_spot ** 2) + r_sphere
excitation_error = z_sphere - z_spot
# Mask parameters corresponding to excited reflections.
intersection = np.abs(excitation_error) < max_excitation_error
intersection_coordinates = cartesian_coordinates[intersection]
excitation_error = excitation_error[intersection]