Beispiel #1
0
def nickel_kikuchi_band(nickel_rlp, nickel_rotations, pc1):
    rlp = nickel_rlp.symmetrise()

    phase = rlp.phase
    hkl = rlp.hkl.data

    nav_shape = (5, 5)

    detector = kp.detectors.EBSDDetector(
        shape=(60, 60),
        binning=8,
        px_size=70,
        pc=np.ones(nav_shape + (3, )) * pc1,
        sample_tilt=70,
        tilt=0,
        convention="tsl",
    )

    nav_dim = detector.navigation_dimension
    navigation_axes = (1, 2)[:nav_dim]

    # Output shape is (3, n, 3) or (3, ny, nx, 3)
    det2recip = detector2reciprocal_lattice(
        sample_tilt=detector.sample_tilt,
        detector_tilt=detector.tilt,
        lattice=phase.structure.lattice,
        rotation=nickel_rotations.reshape(*nav_shape),
    )

    # Output shape is (nhkl, n, 3) or (nhkl, ny, nx, 3)
    hkl_detector = np.tensordot(hkl, det2recip, axes=(1, 0))
    # Determine whether a band is visible in a pattern
    upper_hemisphere = hkl_detector[..., 2] > 0
    is_in_some_pattern = np.sum(upper_hemisphere, axis=navigation_axes) != 0
    # Get bands that are in some pattern and their coordinates in the
    # proper shape
    hkl = hkl[is_in_some_pattern, ...]
    hkl_in_pattern = upper_hemisphere[is_in_some_pattern, ...].T
    hkl_detector = np.moveaxis(hkl_detector[is_in_some_pattern],
                               source=0,
                               destination=nav_dim)

    return kp.simulations.features.KikuchiBand(
        phase=phase,
        hkl=hkl,
        hkl_detector=hkl_detector,
        in_pattern=hkl_in_pattern,
        gnomonic_radius=detector.r_max,
    )
Beispiel #2
0
    def geometrical_simulation(
        self,
        reciprocal_lattice_point: Optional[ReciprocalLatticePoint] = None
    ) -> GeometricalEBSDSimulation:
        """Project a set of Kikuchi bands and zone axes onto the
        detector, one set for each rotation of the unit cell.

        The zone axes are calculated from the Kikuchi bands.

        Parameters
        ----------
        reciprocal_lattice_point
            Crystal planes to project onto the detector. If None, and
            the generator has a phase with a unit cell with a point
            group, a set of planes with minimum distance of 1 Å and
            their symmetrically equivalent planes are used.

        Returns
        -------
        GeometricalEBSDSimulation

        Examples
        --------
        >>> from diffsims.crystallography import ReciprocalLatticePoint
        >>> simgen
        EBSDSimulationGenerator (1,)
        EBSDDetector (60, 60), px_size 1 um, binning 1, tilt 0, pc
        (0.5, 0.5, 0.5)
        <name: . space group: None. point group: None. proper point
        group: None. color: tab:blue>
        Rotation (1,)
        >>> sim1 = simgen.geometrical_simulation()
        >>> sim1.bands.size
        94
        >>> rlp = ReciprocalLatticePoint(
        ...     phase=simgen.phase, hkl=[[1, 1, 1], [2, 0, 0]]
        ... )
        >>> sim2 = simgen.geometrical_simulation()
        >>> sim2.bands.size
        13
        """
        rlp = reciprocal_lattice_point
        if rlp is None and (hasattr(self.phase.point_group, "name") and
                            hasattr(self.phase.structure.lattice, "abcABG")):
            rlp = ReciprocalLatticePoint.from_min_dspacing(self.phase,
                                                           min_dspacing=1)
            rlp = rlp[rlp.allowed].symmetrise()
        elif rlp is None:
            raise ValueError("A ReciprocalLatticePoint object must be passed")
        self._rlp_phase_is_compatible(rlp)

        # Unit cell parameters (called more than once)
        phase = rlp.phase
        hkl = rlp._hkldata

        # Get number of navigation dimensions and navigation axes
        # indices
        n_nav_dims = self.navigation_dimension
        navigation_axes = (1, 2)[:n_nav_dims]

        # Get Kikuchi band coordinates for all bands in all patterns
        # U_Kstar, transformation from detector frame D to reciprocal
        # crystal lattice frame Kstar.
        # Output shape is (3, n, 3) or (3, ny, nx, 3)
        det2recip = detector2reciprocal_lattice(
            sample_tilt=self.detector.sample_tilt,
            detector_tilt=self.detector.tilt,
            lattice=phase.structure.lattice,
            rotation=self.rotations,
        )
        # Output shape is (nhkl, n, 3) or (nhkl, ny, nx, 3)
        hkl_detector = np.tensordot(hkl, det2recip, axes=(1, 0))
        if n_nav_dims == 0:
            hkl_detector = hkl_detector.squeeze()
        # Get bands that are in some pattern
        hkl_is_upper, hkl_in_a_pattern = _get_coordinates_in_upper_hemisphere(
            z_coordinates=hkl_detector[..., 2],
            navigation_axes=navigation_axes)
        hkl = hkl[hkl_in_a_pattern, ...]
        hkl_in_pattern = hkl_is_upper[hkl_in_a_pattern, ...].T
        # Get coordinates in the proper shape
        hkl_detector = np.moveaxis(hkl_detector[hkl_in_a_pattern],
                                   source=0,
                                   destination=n_nav_dims)
        # And store it all
        bands = KikuchiBand(
            phase=phase,
            hkl=hkl,
            hkl_detector=hkl_detector,
            in_pattern=hkl_in_pattern,
            gnomonic_radius=self.detector.r_max,
        )

        # Get zone axes coordinates from Kikuchi bands
        uvw = _get_uvw_from_hkl(hkl=hkl)
        det2direct = detector2direct_lattice(
            sample_tilt=self.detector.sample_tilt,
            detector_tilt=self.detector.tilt,
            lattice=self.phase.structure.lattice,
            rotation=self.rotations,
        )
        uvw_detector = np.tensordot(uvw, det2direct, axes=(1, 0))
        if n_nav_dims == 0:
            uvw_detector = uvw_detector.squeeze()
        uvw_is_upper, uvw_in_a_pattern = _get_coordinates_in_upper_hemisphere(
            z_coordinates=uvw_detector[..., 2],
            navigation_axes=navigation_axes)
        uvw = uvw[uvw_in_a_pattern, ...]
        uvw_in_pattern = uvw_is_upper[uvw_in_a_pattern, ...].T
        uvw_detector = np.moveaxis(uvw_detector[uvw_in_a_pattern],
                                   source=0,
                                   destination=n_nav_dims)
        zone_axes = ZoneAxis(
            phase=phase,
            uvw=uvw,
            uvw_detector=uvw_detector,
            in_pattern=uvw_in_pattern,
            gnomonic_radius=self.detector.r_max,
        )

        return GeometricalEBSDSimulation(
            detector=self.detector,
            rotations=self.rotations,
            bands=bands,
            zone_axes=zone_axes,
        )
Beispiel #3
0
    def geometrical_simulation(
        self,
        reciprocal_lattice_point: Optional[ReciprocalLatticePoint] = None,
    ) -> GeometricalEBSDSimulation:
        """Project a set of center positions of Kikuchi bands on the
        detector, one set for each rotation of the unit cell.

        Parameters
        ----------
        reciprocal_lattice_point :
            Crystal planes to project onto the detector. If None, and
            the generator has a phase with a unit cell with a point
            group, a set of planes with minimum distance of 1 Å and
            their symmetrically equivalent planes are used.

        Returns
        -------
        GeometricalEBSDSimulation

        Examples
        --------
        >>> from diffsims.crystallography import ReciprocalLatticePoint
        >>> simgen
        EBSDSimulationGenerator (1,)
        EBSDDetector (60, 60), px_size 1 um, binning 1, tilt 0, pc
        (0.5, 0.5, 0.5)
        <name: . space group: None. point group: None. proper point
        group: None. color: tab:blue>
        Rotation (1,)
        >>> sim1 = simgen.geometrical_simulation()
        >>> sim1.bands.size
        94
        >>> rlp = ReciprocalLatticePoint(
        ...     phase=simgen.phase, hkl=[[1, 1, 1], [2, 0, 0]]
        ... )
        >>> sim2 = simgen.geometrical_simulation()
        >>> sim2.bands.size
        13
        """
        rlp = reciprocal_lattice_point
        if rlp is None and (hasattr(self.phase.point_group, "name") and
                            hasattr(self.phase.structure.lattice, "abcABG")):
            rlp = ReciprocalLatticePoint.from_min_dspacing(self.phase,
                                                           min_dspacing=1)
            rlp = rlp[rlp.allowed].symmetrise()
        elif rlp is None:
            raise ValueError("A ReciprocalLatticePoint object must be passed")
        self._rlp_phase_is_compatible(rlp)

        # Unit cell parameters (called more than once)
        phase = rlp.phase
        hkl = rlp._hkldata

        # Get Kikuchi band coordinates for all bands in all patterns
        # U_Kstar, transformation from detector frame D to reciprocal crystal
        # lattice frame Kstar
        # TODO: Possible bottleneck due to large dot products! Room for
        #  lots of improvements with dask.
        # Output shape is (3, n, 3) or (3, ny, nx, 3)
        det2recip = detector2reciprocal_lattice(
            sample_tilt=self.detector.sample_tilt,
            detector_tilt=self.detector.tilt,
            lattice=phase.structure.lattice,
            rotation=self.rotations,
        )
        # Output shape is (nhkl, n, 3) or (nhkl, ny, nx, 3)
        band_coordinates = np.tensordot(hkl, det2recip, axes=(1, 0))

        # Determine whether a band is visible in a pattern
        upper_hemisphere = band_coordinates[..., 2] > 0
        nav_dim = self.navigation_dimension
        navigation_axes = (1, 2)[:nav_dim]
        is_in_some_pattern = np.sum(upper_hemisphere,
                                    axis=navigation_axes) != 0

        # Get bands that were in some pattern and their coordinates in the
        # proper shape
        hkl = hkl[is_in_some_pattern, ...]
        hkl_in_pattern = upper_hemisphere[is_in_some_pattern, ...].T
        band_coordinates = np.moveaxis(band_coordinates[is_in_some_pattern],
                                       source=0,
                                       destination=nav_dim)

        # And store it all
        bands = KikuchiBand(
            phase=phase,
            hkl=hkl,
            hkl_detector=band_coordinates,
            in_pattern=hkl_in_pattern,
            gnomonic_radius=self.detector.r_max,
        )

        # Get zone axes coordinates
        # U_K, transformation from detector frame D to direct crystal lattice
        # frame K
        #        det2direct = detector2direct_lattice(
        #            sample_tilt=self.detector.sample_tilt,
        #            detector_tilt=self.detector.tilt,
        #            lattice=phase.structure.lattice,
        #            orientation=self.orientations,
        #        )
        #        hkl_transposed_upper = hkl_transposed[..., upper_hemisphere]
        #        axis_coordinates = det2direct.T.dot(hkl_transposed_upper).T
        #        zone_axes = ZoneAxis(
        #            phase=phase, hkl=upper_hkl, coordinates=axis_coordinates
        #        )

        return GeometricalEBSDSimulation(
            detector=self.detector,
            rotations=self.rotations,
            bands=bands,
            #            zone_axes=zone_axes,
        )