def filter_detector_edge(self, exclude_width, *args, **kwargs): """Filter the diffraction vectors to accept only those not within a user specified proximity to the detector edge. Parameters ---------- exclude_width : int The width of the region adjacent to the detector edge from which vectors will be excluded. *args: Arguments to be passed to map(). **kwargs: Keyword arguments to map(). Returns ------- filtered_vectors : DiffractionVectors Diffraction vectors within allowed detector region. """ x_threshold = ( self.pixel_calibration * (self.detector_shape[0] / 2) - self.pixel_calibration * exclude_width ) y_threshold = ( self.pixel_calibration * (self.detector_shape[1] / 2) - self.pixel_calibration * exclude_width ) # If ragged the signal axes will not be defined if len(self.axes_manager.signal_axes) == 0: filtered_vectors = self.map( filter_vectors_edge_ragged, x_threshold=x_threshold, y_threshold=y_threshold, inplace=False, *args, **kwargs ) # Type assignment to DiffractionVectors for return filtered_vectors = DiffractionVectors(filtered_vectors) filtered_vectors.axes_manager.set_signal_dimension(0) # Otherwise easier to calculate. else: x_inbounds = ( np.absolute(self.data.T[0]) < x_threshold ) # True if vector is good to go y_inbounds = np.absolute(self.data.T[1]) < y_threshold filtered_vectors = self.data[np.logical_and(x_inbounds, y_inbounds)] # Type assignment to DiffractionVectors for return filtered_vectors = DiffractionVectors(filtered_vectors) filtered_vectors.axes_manager.set_signal_dimension(1) transfer_navigation_axes(filtered_vectors, self) return filtered_vectors
def get_crystallographic_map(self, *args, **kwargs): """Obtain a crystallographic map specifying the best matching phase and orientation at each probe position with corresponding metrics. Returns ------- cryst_map : Signal2D Crystallographic mapping results containing the best matching phase and orientation at each navigation position with associated metrics. The Signal at each navigation position is an array of, [phase, np.array((z,x,z)), dict(metrics)] which defines the phase, orientation as Euler angles in the zxz convention and metrics associated with the matching. Metrics for template matching results are 'match_rate' 'total_error' 'orientation_reliability' 'phase_reliability' """ crystal_map = self.map( crystal_from_vector_matching, inplace=False, *args, **kwargs ) crystal_map = transfer_navigation_axes(crystal_map, self) return crystal_map
def filter_magnitude(self, min_magnitude, max_magnitude, *args, **kwargs): """Filter the diffraction vectors to accept only those with a magnitude within a user specified range. Parameters ---------- min_magnitude : float Minimum allowed vector magnitude. max_magnitude : float Maximum allowed vector magnitude. *args: Arguments to be passed to map(). **kwargs: Keyword arguments to map(). Returns ------- filtered_vectors : DiffractionVectors Diffraction vectors within allowed magnitude tolerances. """ # If ragged the signal axes will not be defined if len(self.axes_manager.signal_axes) == 0: filtered_vectors = self.map( filter_vectors_ragged, min_magnitude=min_magnitude, max_magnitude=max_magnitude, inplace=False, *args, **kwargs ) # Type assignment to DiffractionVectors for return filtered_vectors = DiffractionVectors(filtered_vectors) filtered_vectors.axes_manager.set_signal_dimension(0) # Otherwise easier to calculate. else: magnitudes = self.get_magnitudes() magnitudes.data[magnitudes.data < min_magnitude] = 0 magnitudes.data[magnitudes.data > max_magnitude] = 0 filtered_vectors = self.data[np.where(magnitudes)] # Type assignment to DiffractionVectors for return filtered_vectors = DiffractionVectors(filtered_vectors) filtered_vectors.axes_manager.set_signal_dimension(1) transfer_navigation_axes(filtered_vectors, self) return filtered_vectors
def get_pdf(self, s_min, s_max=None, r_min=0, r_max=20, r_increment=0.01): """Calculates the pdf from the reduced intensity signal. Parameters ---------- s_min : float Minimum scattering vector s for the pdf calculation. Note that s is defined here as s = 2 sin(theta)/lambda = 1/d. s_max : float Maximum scattering vector s for the pdf calculation. Note that s is defined here as s = 2 sin(theta)/lambda = 1/d. r_cutoff : list of float A list with the format [<r_min>, <r_max>], which sets the limits of the real space axis in the calculated PDF. r_increment : float Step size in r in the extracted PDF. Returns ------- pdf : PDF1D A signal of pair distribution functions. """ s_scale = self.signal.axes_manager.signal_axes[0].scale if s_max is None: s_max = self.signal.axes_manager.signal_axes[0].size * s_scale print("s_max set to maximum of signal.") r_values = np.arange(r_min, r_max, r_increment) r_values = r_values.reshape(1, r_values.size) s_limits = [int(s_min / s_scale), int(s_max / s_scale)] # check that these aren't out of bounds if s_limits[1] > self.signal.axes_manager.signal_axes[0].size: raise ValueError( "User specified s_max is larger than the maximum " "scattering vector magnitude in the data. Please reduce " "s_max or use s_max=None to use the full scattering range.") s_values = np.arange(s_limits[0], s_limits[1], 1) * s_scale s_values = s_values.reshape(s_values.size, 1) # column vector limited_red_int = self.signal.isig[s_limits[0]:s_limits[1]].data pdf_sine = np.sin(2 * np.pi * np.matmul(s_values, r_values)) # creates a vector of the pdf rpdf = PairDistributionFunction1D(8 * np.pi * s_scale * np.matmul(limited_red_int, pdf_sine)) signal_axis = rpdf.axes_manager.signal_axes[0] signal_axis.scale = r_increment signal_axis.name = "Radius r" signal_axis.units = "$Å$" rpdf = transfer_navigation_axes(rpdf, self.signal) title = self.signal.metadata.General.title rpdf.metadata.General.title = f"Pair distribution function of {title}" return rpdf
def refine_n_best_orientations( self, orientations, accelarating_voltage, camera_length, n_best=0, rank=0, index_error_tol=0.2, vary_angles=True, vary_center=False, vary_scale=False, method="leastsq", ): """Refines the best orientation and assigns hkl indices to diffraction vectors. Parameters ---------- orientations : VectorMatchingResults List of orientations to refine, must be an instance of `VectorMatchingResults`. accelerating_voltage : float The acceleration voltage with which the data was acquired. camera_length : float The camera length in meters. n_best : int Refine the best `n` orientations starting from `rank`. With `n_best=0` (default), all orientations are refined. rank : int The rank of the solution to start from. 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. Returns ------- indexation_results : VectorMatchingResults Navigation axes of the diffraction vectors signal containing vector indexation results for each probe position. """ vectors = self.vectors library = self.library matched = orientations.map( _refine_best_orientations, vectors=vectors, library=library, accelarating_voltage=accelarating_voltage, camera_length=camera_length, n_best=n_best, rank=rank, method="leastsq", verbose=False, vary_angles=vary_angles, vary_center=vary_center, vary_scale=vary_scale, inplace=False, parallel=False, ) indexation = matched.isig[0] rhkls = matched.isig[1].data indexation_results = VectorMatchingResults(indexation) indexation_results.vectors = vectors indexation_results.hkls = rhkls indexation_results = transfer_navigation_axes(indexation_results, vectors.cartesian) return indexation_results
def index_vectors( self, mag_tol, angle_tol, index_error_tol, n_peaks_to_index, n_best, *args, **kwargs, ): """Assigns hkl indices to diffraction vectors. Parameters ---------- mag_tol : float The maximum absolute error in diffraction vector magnitude, in units of reciprocal Angstroms, allowed for indexation. angle_tol : float The maximum absolute error in inter-vector angle, in units of degrees, allowed for indexation. index_error_tol : float Max allowed error in peak indexation for classifying it as indexed, calculated as :math:`|hkl_calculated - round(hkl_calculated)|`. n_peaks_to_index : int The maximum number of peak to index. n_best : int The maximum number of good solutions to be retained. *args : arguments Arguments passed to the map() function. **kwargs : arguments Keyword arguments passed to the map() function. Returns ------- indexation_results : VectorMatchingResults Navigation axes of the diffraction vectors signal containing vector indexation results for each probe position. """ vectors = self.vectors library = self.library matched = vectors.cartesian.map( match_vectors, library=library, mag_tol=mag_tol, angle_tol=np.deg2rad(angle_tol), index_error_tol=index_error_tol, n_peaks_to_index=n_peaks_to_index, n_best=n_best, inplace=False, *args, **kwargs, ) indexation = matched.isig[0] rhkls = matched.isig[1].data indexation_results = VectorMatchingResults(indexation) indexation_results.vectors = vectors indexation_results.hkls = rhkls indexation_results = transfer_navigation_axes(indexation_results, vectors.cartesian) vectors.hkls = rhkls return indexation_results