Exemplo n.º 1
0
    def calculate_cartesian_coordinates(
        self, accelerating_voltage, camera_length, *args, **kwargs
    ):
        """Get cartesian coordinates of the diffraction vectors.

        Parameters
        ----------
        accelerating_voltage : float
            The acceleration voltage with which the data was acquired.
        camera_length : float
            The camera length in meters.
        """
        # Imported here to avoid circular dependency
        from diffsims.utils.sim_utils import get_electron_wavelength

        wavelength = get_electron_wavelength(accelerating_voltage)
        self.cartesian = self.map(
            detector_to_fourier,
            wavelength=wavelength,
            camera_length=camera_length * 1e10,
            inplace=False,
            parallel=False,  # TODO: For testing
            *args,
            **kwargs
        )
Exemplo n.º 2
0
 def __init__(
     self,
     accelerating_voltage,
     scattering_params="lobato",
     precession_angle=0,
     shape_factor_model="lorentzian",
     approximate_precession=True,
     minimum_intensity=1e-20,
     **kwargs,
 ):
     self.wavelength = get_electron_wavelength(accelerating_voltage)
     self.precession_angle = precession_angle
     self.approximate_precession = approximate_precession
     if isinstance(shape_factor_model, str):
         if shape_factor_model in _shape_factor_model_mapping.keys():
             self.shape_factor_model = _shape_factor_model_mapping[
                 shape_factor_model]
         else:
             raise NotImplementedError(
                 f"{shape_factor_model} is not a recognized shape factor "
                 f"model, choose from: {_shape_factor_model_mapping.keys()} "
                 f"or provide your own function.")
     else:
         self.shape_factor_model = shape_factor_model
     self.minimum_intensity = minimum_intensity
     self.shape_factor_kwargs = kwargs
     if scattering_params in ["lobato", "xtables"]:
         self.scattering_params = scattering_params
     else:
         raise NotImplementedError(
             "The scattering parameters `{}` is not implemented. "
             "See documentation for available "
             "implementations.".format(scattering_params))
Exemplo n.º 3
0
 def get_azimuthal_integral1d(self, npt_rad, beam_energy=None, **kwargs):
     if beam_energy is None and self.beam_energy is not None:
         beam_energy = self.beam_energy
     if beam_energy is not None:
         wavelength = get_electron_wavelength(self.beam_energy) * 1e-10
     else:
         wavelength = None
     integration = super().get_azimuthal_integral1d(
         npt_rad=npt_rad, wavelength=wavelength, **kwargs
     )
     return integration
Exemplo n.º 4
0
    def __init__(self,
                 accelerating_voltage,
                 detector,
                 reciprocal_mesh=False,
                 debye_waller_factors=None):
        self.wavelength = get_electron_wavelength(accelerating_voltage)
        # Always store a 'real' mesh
        self.detector = detector if not reciprocal_mesh else from_recip(
            detector)

        if debye_waller_factors:
            raise NotImplementedError('Not implemented for this simulator')
        self.debye_waller_factors = debye_waller_factors or {}
Exemplo n.º 5
0
 def set_ai(
     self, center=None, energy=None, affine=None, radial_range=None, **kwargs
 ):
     if energy is None and self.beam_energy is not None:
         energy = self.beam_energy
     if energy is not None:
         wavelength = get_electron_wavelength(energy) * 1e-10
     else:
         wavelength = None
     ai = super().set_ai(
         center=center,
         wavelength=wavelength,
         affine=affine,
         radial_range=radial_range,
         **kwargs
     )
     return ai
Exemplo n.º 6
0
    def __init__(self,
                 accelerating_voltage,
                 max_excitation_error,
                 debye_waller_factors=None,
                 scattering_params='lobato'):
        self.wavelength = get_electron_wavelength(accelerating_voltage)
        self.max_excitation_error = max_excitation_error
        self.debye_waller_factors = debye_waller_factors or {}

        scattering_params_dict = {'lobato': 'lobato', 'xtables': 'xtables'}
        if scattering_params in scattering_params_dict:
            self.scattering_params = scattering_params_dict[scattering_params]
        else:
            raise NotImplementedError(
                "The scattering parameters `{}` is not implemented. "
                "See documentation for available "
                "implementations.".format(scattering_params))
Exemplo n.º 7
0
 def __init__(self,
              accelerating_voltage,
              max_excitation_error=None,
              debye_waller_factors={},
              scattering_params="lobato"):
     if max_excitation_error is not None:
         print(
             "This class changed in v0.3 and no longer takes a maximum_excitation_error"
         )
     self.wavelength = get_electron_wavelength(accelerating_voltage)
     self.debye_waller_factors = debye_waller_factors
     if scattering_params in ["lobato", "xtables"]:
         self.scattering_params = scattering_params
     else:
         raise NotImplementedError(
             "The scattering parameters `{}` is not implemented. "
             "See documentation for available "
             "implementations.".format(scattering_params))
Exemplo n.º 8
0
def _refine_orientation(
    solution,
    k_xy,
    structure_library,
    accelarating_voltage,
    camera_length,
    index_error_tol=0.2,
    method="leastsq",
    vary_angles=True,
    vary_center=False,
    vary_scale=False,
    verbose=False,
):
    """
    Refine a single orientation agains the given cartesian vector coordinates.

    Parameters
    ----------
    solution : OrientationResult
        Namedtuple containing the starting orientation
    k_xy : DiffractionVectors
        DiffractionVectors (x,y pixel format) to be indexed.
    structure_library : :obj:`diffsims:StructureLibrary` Object
        Dictionary of structures and associated orientations for which
        electron diffraction is to be simulated.
    index_error_tol : float
        Max allowed error in peak indexation for classifying it as indexed,
        calculated as :math:`|hkl_calculated - round(hkl_calculated)|`.
    method : str
        Minimization algorithm to use, choose from:
        'leastsq', 'nelder', 'powell', 'cobyla', 'least-squares'.
        See `lmfit` documentation (https://lmfit.github.io/lmfit-py/fitting.html)
        for more information.
    vary_angles : bool,
        Free the euler angles (rotation matrix) during the refinement.
    vary_center : bool
        Free the center of the diffraction pattern (beam center) during the refinement.
    vary_scale : bool
        Free the scale (i.e. pixel size) of the diffraction vectors during refinement.
    verbose : bool
        Be more verbose

    Returns
    -------
    result : OrientationResult
        Container for the orientation refinement results
    """

    # prepare reciprocal_lattice
    structure = structure_library.structures[solution.phase_index]
    lattice_recip = structure.lattice.reciprocal()

    def objfunc(params, k_xy, lattice_recip, wavelength, camera_length):
        cx = params["center_x"].value
        cy = params["center_y"].value
        ai = params["ai"].value
        aj = params["aj"].value
        ak = params["ak"].value
        scale = params["scale"].value

        rotmat = euler2mat(ai, aj, ak)

        k_xy = k_xy + np.array((cx, cy)) * scale
        cart = detector_to_fourier(k_xy, wavelength, camera_length)

        intermediate = cart.dot(rotmat.T)  # Must use the transpose here
        hklss = lattice_recip.fractional(intermediate) * scale

        rhklss = np.rint(hklss)
        ehklss = np.abs(hklss - rhklss)

        return ehklss

    ai, aj, ak = mat2euler(solution.rotation_matrix)

    params = lmfit.Parameters()
    params.add("center_x", value=solution.center_x, vary=vary_center)
    params.add("center_y", value=solution.center_y, vary=vary_center)
    params.add("ai", value=ai, vary=vary_angles)
    params.add("aj", value=aj, vary=vary_angles)
    params.add("ak", value=ak, vary=vary_angles)
    params.add("scale",
               value=solution.scale,
               vary=vary_scale,
               min=0.8,
               max=1.2)

    wavelength = get_electron_wavelength(accelarating_voltage)
    camera_length = camera_length * 1e10
    args = k_xy, lattice_recip, wavelength, camera_length

    res = lmfit.minimize(objfunc, params, args=args, method=method)

    if verbose:  # pragma: no cover
        lmfit.report_fit(res)

    p = res.params

    ai, aj, ak = p["ai"].value, p["aj"].value, p["ak"].value
    scale = p["scale"].value
    center_x = params["center_x"].value
    center_y = params["center_y"].value

    rotation_matrix = euler2mat(ai, aj, ak)

    k_xy = k_xy + np.array((center_x, center_y)) * scale
    cart = detector_to_fourier(k_xy,
                               wavelength=wavelength,
                               camera_length=camera_length)

    intermediate = cart.dot(rotation_matrix.T)  # Must use the transpose here
    hklss = lattice_recip.fractional(intermediate)

    rhklss = np.rint(hklss)

    error_hkls = res.residual.reshape(-1, 3)
    error_mean = np.mean(error_hkls)

    valid_peak_mask = np.max(error_hkls, axis=-1) < index_error_tol
    valid_peak_count = np.count_nonzero(valid_peak_mask, axis=-1)

    num_peaks = len(k_xy)

    match_rate = (valid_peak_count * (1 / num_peaks)) if num_peaks else 0

    orientation = OrientationResult(
        phase_index=solution.phase_index,
        rotation_matrix=rotation_matrix,
        match_rate=match_rate,
        error_hkls=error_hkls,
        total_error=error_mean,
        scale=scale,
        center_x=center_x,
        center_y=center_y,
    )

    res = np.empty(2, dtype=np.object)
    res[0] = orientation
    res[1] = rhklss

    return res
Exemplo n.º 9
0
 def __init__(self, accelerating_voltage, detector, reciprocal_mesh=False):
     self.wavelength = get_electron_wavelength(accelerating_voltage)
     # Always store a 'real' mesh
     self.detector = detector if not reciprocal_mesh else from_recip(detector)
Exemplo n.º 10
0
def test_get_electron_wavelength(accelerating_voltage, wavelength):
    val = get_electron_wavelength(accelerating_voltage=accelerating_voltage)
    np.testing.assert_almost_equal(val, wavelength)