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 )
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))
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
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 {}
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
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))
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))
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
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)
def test_get_electron_wavelength(accelerating_voltage, wavelength): val = get_electron_wavelength(accelerating_voltage=accelerating_voltage) np.testing.assert_almost_equal(val, wavelength)