def get_diffracting_pixels_map(self, in_range=None, binary=False): """Map of the number of vectors at each navigation position. Parameters ---------- in_range : tuple Tuple (min_magnitude, max_magnitude) the minimum and maximum magnitude of vectors to be used to form the map. binary : boolean If True a binary image with diffracting pixels taking value == 1 is returned. Returns ------- crystim : Signal2D 2D map of diffracting pixels. """ if in_range: filtered = self.filter_magnitude(in_range[0], in_range[1]) xim = filtered.map(get_npeaks, inplace=False).as_signal2D((0, 1)) else: xim = self.map(get_npeaks, inplace=False).as_signal2D((0, 1)) # Make binary if specified if binary is True: xim = xim >= 1.0 # Set properties xim = transfer_navigation_axes_to_signal_axes(xim, self) xim.change_dtype("float") xim.set_signal_type("signal2d") xim.metadata.General.title = "Diffracting Pixels Map" return xim
def get_phase_map(self): """Obtain a map of the best matching phase at each navigation position.""" phase_map = self.isig[0].as_signal2D((0, 1)) phase_map = transfer_navigation_axes_to_signal_axes(phase_map, self) phase_map.change_dtype(np.int) return phase_map
def get_diffracting_pixels_map(self, binary=False): """Map of the number of vectors at each navigation position. Parameters ---------- binary : boolean If True a binary image with diffracting pixels taking value == 1 is returned. Returns ------- crystim : Signal2D 2D map of diffracting pixels. """ crystim = self.map(get_npeaks, inplace=False).as_signal2D((0, 1)) if binary is True: crystim = crystim == 1 crystim.change_dtype('float') # Set calibration to same as signal crystim = transfer_navigation_axes_to_signal_axes(crystim, self) return crystim
def get_concentric_vdf_images(self, k_min, k_max, k_steps, normalize=False): """Obtain the intensity scattered at each navigation position in an ElectronDiffraction2D Signal by summation over a series of concentric in annuli between a specified inner and outer radius in a number of steps. Parameters ---------- k_min : float Minimum radius of the annular integration window in reciprocal angstroms. k_max : float Maximum radius of the annular integration window in reciprocal angstroms. k_steps : int Number of steps within the annular integration window Returns ------- vdfs : VDFImage VDFImage object containing virtual dark field images for all steps within the annulus. """ k_step = (k_max - k_min) / k_steps k0s = np.linspace(k_min, k_max - k_step, k_steps) k1s = np.linspace(k_min + k_step, k_max, k_steps) ks = np.array((k0s, k1s)).T vdfs = [] for k in ks: annulus = roi.CircleROI(cx=0, cy=0, r=k[1], r_inner=k[0]) vdf = annulus(self.signal, axes=self.signal.axes_manager.signal_axes) vdfs.append(vdf.sum((2, 3)).as_signal2D((0, 1)).data) vdfim = VDFImage(np.asarray(vdfs)) if normalize: vdfim.map(normalize_vdf) # Set calibration to same as signal vdfim = transfer_navigation_axes_to_signal_axes(vdfim, self.signal) return vdfim
def get_vector_vdf_images(self, radius, normalize=False): """Obtain the intensity scattered to each diffraction vector at each navigation position in an ElectronDiffraction2D Signal by summation in a circular window of specified radius. Parameters ---------- radius : float Radius of the integration window in reciprocal angstroms. normalize : boolean If True each VDF image is normalized so that the maximum intensity in each VDF is 1. Returns ------- vdfs : VDFImage VDFImage object containing virtual dark field images for all unique vectors. """ if self.vectors: vdfs = [] for v in self.vectors.data: disk = roi.CircleROI(cx=v[0], cy=v[1], r=radius, r_inner=0) vdf = disk(self.signal, axes=self.signal.axes_manager.signal_axes) vdfs.append(vdf.sum((2, 3)).as_signal2D((0, 1)).data) vdfim = VDFImage(np.asarray(vdfs)) if normalize: vdfim.map(normalize_vdf) else: raise ValueError( "DiffractionVectors not specified by user. Please " "initialize VDFGenerator with some vectors. ") # Set calibration to same as signal vdfim = transfer_navigation_axes_to_signal_axes(vdfim, self.signal) # Assign vectors used to generate images to vdfim attribute. vdfim.vectors = self.vectors vdfim.vectors = transfer_signal_axes(vdfim.vectors, self.vectors) return vdfim
def get_orientation_map(self): """Obtain a map of the rotational angle associated with the best matching crystal orientation at each navigation position. Returns ------- orientation_map : Signal2D The rotation angle assocaiated with the orientation at each navigation position. """ eulers = self.isig[1] eulers.map(_euler2axangle_signal, inplace=True) orientation_map = eulers.as_signal2D((0, 1)) orientation_map = transfer_navigation_axes_to_signal_axes(orientation_map, self) # Since vector matching results returns in object form, eulers inherits # it. orientation_map.change_dtype("float") return orientation_map
def get_image_variance(self, dqe): """Calculates the variance in scattered intensity as a function of scattering vector. The calculated variance is normalised by the mean squared, as is appropriate for the distribution of intensities. This causes a problem if Poisson noise is significant in the data, resulting in a divergence of the Poisson noise term. To in turn remove this effect, we subtract a dqe/mean_dp term (although it is suggested that dqe=1) from the data, creating a "poisson noise-free" corrected variance pattern. DQE is fitted to make this pattern flat. Parameters ---------- dqe : float Detective quantum efficiency of the detector for Poisson noise correction. Returns ------- varims : ImageVariance A two dimensional Signal class object containing the mean DP, mean squared DP, and variance DP, and a Poisson noise-corrected variance DP. """ im = self.signal.T mean_im = im.mean((0, 1)) meansq_im = Signal2D(np.square(im.data)).mean((0, 1)) normvar = (meansq_im.data / np.square(mean_im.data)) - 1.0 var_im = Signal2D(normvar) corr_var_array = normvar - (np.divide(dqe, mean_im.data)) corr_var_array[np.invert(np.isfinite(corr_var_array))] = 0 corr_var = Signal2D(corr_var_array) varims = stack((mean_im, meansq_im, var_im, corr_var)) sig_x = varims.data.shape[1] sig_y = varims.data.shape[2] iv = ImageVariance(varims.data.reshape((2, 2, sig_x, sig_y))) iv = transfer_navigation_axes_to_signal_axes(iv, self.signal) return iv
def get_metric_map(self, metric): """Obtain a map of an indexation / matching metric at each navigation position. Parameters ---------- metric : str String identifier for the indexation / matching metric to be mapped, for template matching valid metrics are {'correlation', 'orientation_reliability', 'phase_reliability'}. For vector matching valid metrics are {'match_rate', 'ehkls', 'total_error', 'orientation_reliability', 'phase_reliability'}. Returns ------- metric_map : Signal2D A map of the specified metric at each navigation position. Notes ----- For template matching, orientation reliability is given by 100 * (1 - second_best_correlation/best_correlation) and phase reliability is given by 100 * (1 - second_best_correlation_of_other_phase/best_correlation) For vector matching, orientation reliability is given by 100 * (1 - lowest_error/second_lowest_error) and phase reliability is given by 100 * (1 - lowest_error/lowest_error_of_other_phase) """ if self.method == "template_matching": template_metrics = [ "correlation", "orientation_reliability", "phase_reliability", ] if metric in template_metrics: metric_map = ( self.isig[2] .map(_metric_from_dict, metric=metric, inplace=False) .as_signal2D((0, 1)) ) else: raise ValueError( "The metric `{}` is not valid for template " "matching results.".format(metric) ) elif self.method == "vector_matching": vector_metrics = [ "match_rate", "ehkls", "total_error", "orientation_reliability", "phase_reliability", ] if metric in vector_metrics: metric_map = ( self.isig[2] .map(_metric_from_dict, metric=metric, inplace=False) .as_signal2D((0, 1)) ) else: raise ValueError( "The metric `{}` is not valid for vector " "matching results.".format(metric) ) else: raise ValueError( "The crystallographic mapping method must be " "specified, as an attribute, as either " "template_matching or vector_matching." ) metric_map = transfer_navigation_axes_to_signal_axes(metric_map, self) return metric_map