Пример #1
0
    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 : CrystallographicMap
            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
                'correlation'
                'orientation_reliability'
                'phase_reliability'

        """
        # TODO: Add alternative methods beyond highest correlation score.
        crystal_map = self.map(crystal_from_template_matching,
                               inplace=False,
                               *args,
                               **kwargs)

        cryst_map = CrystallographicMap(crystal_map)
        cryst_map = transfer_navigation_axes(cryst_map, self)
        cryst_map.method = 'template_matching'

        return cryst_map
Пример #2
0
    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 = np.array(matched.isig[0].data.tolist(), dtype='object')
        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
Пример #3
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 pyxem.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)
        transfer_navigation_axes(self.cartesian, self)
Пример #4
0
    def correlate(self, n_largest=5, keys=[], mask=None, *args, **kwargs):
        """Correlates the library of simulated diffraction patterns with the
        electron diffraction signal.

        Parameters
        ----------
        n_largest : int
            The n orientations with the highest correlation values are returned.
        keys : list
            If more than one phase present in library it is recommended that
            these are submitted. This allows a mapping from the number to the
            phase.  For example, keys = ['si','ga'] will have an output with 0
            for 'si' and 1 for 'ga'.
        mask : Array
            Array with the same size as signal (in navigation) True False
        *args : arguments
            Arguments passed to map().
        **kwargs : arguments
            Keyword arguments passed map().

        Returns
        -------
        matching_results : TemplateMatchingResults
            Navigation axes of the electron diffraction signal containing
            correlation results for each diffraction pattern, in the form
                [Library Number , [z, x, z], Correlation Score]

        """
        signal = self.signal
        library = self.library
        if mask is None:
            # index at all real space pixels
            sig_shape = signal.axes_manager.navigation_shape
            mask = hs.signals.Signal1D(np.ones(
                (sig_shape[0], sig_shape[1], 1)))

        matches = signal.map(correlate_library,
                             library=library,
                             n_largest=n_largest,
                             keys=keys,
                             mask=mask,
                             inplace=False,
                             **kwargs)
        matching_results = TemplateMatchingResults(matches)

        matching_results = transfer_navigation_axes(matching_results, signal)

        return matching_results
Пример #5
0
    def index_vectors(self,
                      mag_tol,
                      angle_tol,
                      index_error_tol,
                      n_peaks_to_index,
                      n_best,
                      keys=[],
                      *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 |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.
        keys : list
            If more than one phase present in library it is recommended that
            these are submitted. This allows a mapping from the number to the
            phase.  For example, keys = ['si','ga'] will have an output with 0
            for 'si' and 1 for 'ga'.
        *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,
            keys=keys,
            inplace=False,
            parallel=False,  # TODO: For testing
            *args,
            **kwargs)
        indexation = np.array(matched.isig[0].data.tolist(), dtype='object')
        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
Пример #6
0
    def correlate(self,
                  n_largest=5,
                  mask=None,
                  inplane_rotations=np.arange(0, 360, 1),
                  max_peaks=100,
                  *args,
                  **kwargs):
        """Correlates the library of simulated diffraction patterns with the
        electron diffraction signal.

        Parameters
        ----------
        n_largest : int
            The n orientations with the highest correlation values are returned.
        mask : Array
            Array with the same size as signal (in navigation) True False
        inplane_rotations : ndarray
            Array of inplane rotation angles in degrees. Defaults to 0-360 degrees
            at 1 degree resolution.
        max_peaks : int
            Maximum number of peaks to consider when comparing a template to
            the diffraction pattern. The strongest peaks are kept.
        *args : arguments
            Arguments passed to map().
        **kwargs : arguments
            Keyword arguments passed map().

        Returns
        -------
        matching_results : TemplateMatchingResults
            Navigation axes of the electron diffraction signal containing
            correlation results for each diffraction pattern, in the form
            [Library Number , [z, x, z], Correlation Score]

        """
        signal = self.signal
        library = self.library
        inplane_rotations = np.deg2rad(inplane_rotations)
        num_inplane_rotations = inplane_rotations.shape[0]
        sig_shape = signal.axes_manager.signal_shape
        signal_half_width = sig_shape[0] / 2

        if mask is None:
            # Index at all real space pixels
            mask = 1

        # Create a copy of the library, cropping and padding the peaks to match
        # max_peaks. Also create rotated pixel coordinates according to
        # inplane_rotations
        rotation_matrices_2d = np.array([[[np.cos(t), np.sin(t)],
                                          [-np.sin(t), np.cos(t)]]
                                         for t in inplane_rotations])
        cropped_library = {}

        for phase_name, phase_entry in library.items():
            num_orientations = len(phase_entry['orientations'])
            intensities_jagged = phase_entry['intensities']
            intensities = np.zeros((num_orientations, max_peaks))
            pixel_coords_jagged = phase_entry['pixel_coords']
            pixel_coords = np.zeros(
                (num_inplane_rotations, num_orientations, max_peaks, 2))
            for i in range(num_orientations):
                num_peaks = min(pixel_coords_jagged[i].shape[0], max_peaks)
                intensities[i, :num_peaks] = intensities_jagged[i][:num_peaks]
                # Get and compute pixel coordinates for all rotations about the
                # center, clipped to the detector size and rounded to integer positions.
                pixel_coords[:, i, :num_peaks] = np.clip(
                    (signal_half_width + rotation_matrices_2d
                     @ (pixel_coords_jagged[i][:num_peaks].T -
                        signal_half_width)).transpose(0, 2, 1),
                    a_min=0,
                    a_max=np.array(sig_shape) - 1)

            np.rint(pixel_coords, out=pixel_coords)
            cropped_library[phase_name] = {
                'orientations': phase_entry['orientations'],
                'pixel_coords': pixel_coords.astype('int'),
                'intensities': intensities,
                'pattern_norms': np.linalg.norm(intensities, axis=1),
            }

        matches = signal.map(correlate_library,
                             library=cropped_library,
                             n_largest=n_largest,
                             mask=mask,
                             inplace=False,
                             **kwargs)

        matching_results = TemplateMatchingResults(matches)
        matching_results = transfer_navigation_axes(matching_results, signal)

        return matching_results