Exemplo n.º 1
0
def nickel_zone_axes(nickel_kikuchi_band, nickel_rotations, pc1):
    bands = nickel_kikuchi_band
    hkl = bands.hkl.data
    phase = bands.phase

    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]

    n_hkl = bands.size
    n_hkl2 = n_hkl**2
    uvw = np.cross(hkl[:, np.newaxis, :], hkl).reshape((n_hkl2, 3))
    not000 = np.count_nonzero(uvw, axis=1) != 0
    uvw = uvw[not000]
    with np.errstate(divide="ignore", invalid="ignore"):
        uvw = uvw / np.gcd.reduce(uvw, axis=1)[:, np.newaxis]
    uvw = np.unique(uvw, axis=0).astype(int)
    det2direct = detector2direct_lattice(
        sample_tilt=detector.sample_tilt,
        detector_tilt=detector.tilt,
        lattice=phase.structure.lattice,
        rotation=nickel_rotations.reshape(*nav_shape),
    )
    uvw_detector = np.tensordot(uvw, det2direct, axes=(1, 0))
    upper_hemisphere = uvw_detector[..., 2] > 0
    is_in_some_pattern = np.sum(upper_hemisphere, axis=navigation_axes) != 0
    uvw = uvw[is_in_some_pattern, ...]
    uvw_in_pattern = upper_hemisphere[is_in_some_pattern, ...].T
    uvw_detector = np.moveaxis(uvw_detector[is_in_some_pattern],
                               source=0,
                               destination=nav_dim)

    return kp.simulations.features.ZoneAxis(
        phase=phase,
        uvw=uvw,
        uvw_detector=uvw_detector,
        in_pattern=uvw_in_pattern,
        gnomonic_radius=detector.r_max,
    )
Exemplo n.º 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,
        )
Exemplo n.º 3
0
    def test_init(
        self,
        nickel_kikuchi_band,
        detector,
        nickel_rotations,
        hkl_slices,
        desired_nav_shape,
        desired_nav_dims,
        desired_data_shape,
    ):
        bands = nickel_kikuchi_band[hkl_slices]
        phase = bands.phase

        n_nav_dims = bands.navigation_dimension
        navigation_axes = (1, 2)[:n_nav_dims]

        rotations = nickel_rotations.reshape(5, 5)[hkl_slices[:2]]

        uvw = _get_uvw_from_hkl(bands.hkl.data)
        det2direct = detector2direct_lattice(
            sample_tilt=detector.sample_tilt,
            detector_tilt=detector.tilt,
            lattice=phase.structure.lattice,
            rotation=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)
        za = ZoneAxis(
            phase=phase,
            uvw=uvw,
            uvw_detector=uvw_detector,
            in_pattern=uvw_in_pattern,
            gnomonic_radius=detector.r_max,
        )

        assert za.navigation_shape == desired_nav_shape
        assert za.navigation_dimension == desired_nav_dims
        assert za._data_shape == desired_data_shape

        x_detector = uvw_detector[..., 0]
        y_detector = uvw_detector[..., 1]
        z_detector = uvw_detector[..., 2]
        assert np.allclose(za.x_detector, x_detector)
        assert np.allclose(za.y_detector, y_detector)
        assert np.allclose(za.z_detector, z_detector)

        with np.errstate(divide="ignore"):
            desired_x_gnomonic = x_detector / z_detector
            desired_y_gnomonic = y_detector / z_detector
        assert np.allclose(za.x_gnomonic, desired_x_gnomonic)
        assert np.allclose(za.y_gnomonic, desired_y_gnomonic)
        assert np.allclose(
            za.r_gnomonic,
            np.sqrt(desired_x_gnomonic**2 + desired_y_gnomonic**2),
        )