コード例 #1
0
def test_get_diffraction_image(n, vol_shape, grid_shape, precession,
                               wavelength):
    coords, species = create_atoms(n, vol_shape)
    x = [np.linspace(0, vol_shape[i], grid_shape[i]) for i in range(3)]
    if precession:
        precession = (1e-3, 20)
    else:
        precession = (0, 1)

    params = {
        "dtype": ("f4", "c8"),
        "ZERO": 1e-10,
        "GPU": False,
        "pointwise": True
    }
    val1 = get_diffraction_image(coords, species, probe, x, wavelength,
                                 precession, **params)
    val2 = get_diffraction_image(coords, species, probe, x, 0, (0, 1),
                                 **params)

    if precession[0] > 0:
        val1 = val1[2:-2, 2:-2]
        val2 = val2[2:-2, 2:-2]

    assert val1.shape == val2.shape
    if precession[0] == 0:
        assert val1.shape == grid_shape[:2]
    np.testing.assert_allclose(val1, val2, 1e-2, 1e-4)
コード例 #2
0
    def calculate_ed_data(
        self,
        structure,
        probe,
        slice_thickness,
        probe_centre=None,
        z_range=200,
        precessed=False,
        dtype="float64",
        ZERO=1e-14,
        mode="kinematic",
        **kwargs,
    ):
        """
        Calculates single electron diffraction image for particular atomic
        structure and probe.

        Parameters
        ----------
        structure : Structure
            The structure for upon which to perform the calculation
        probe : instance of probeFunction
            Function representing 3D shape of beam
        slice_thickness : float
            Discretisation thickness in the z-axis
        probe_centre : ndarray (or iterable), shape [3] or [2]
            Translation vector for the probe. Either of the same dimension of the
            space or the dimension of the detector. default=None focusses the
            probe at [0,0,0]
        zrange : float
            z-thickness to discretise. Only required if sample is not thick enough to
            fully resolve the Ewald-sphere. Default value is 200.
        precessed : bool, float, or (float, int)
            Dictates whether beam precession is simulated. If False or the float is
            0 then no precession is computed. If <precessed> = (alpha, n) then the
            precession arc of tilt alpha (in degrees) is discretised into n
            projections. If n is not provided then default of 30 is used.
        dtype : str or numpy.dtype
            Defines the precision to use whilst computing diffraction image.
        ZERO : float > 0
            Rounding error permitted in computation of atomic density. This value is
            the smallest value rounded to 0. Default is 1e-14.
        mode : str
            Only <mode>='kinematic' is currently supported.
        kwargs : dictionary
            Extra key-word arguments to pass to child simulator.
            For kinematic: **GPU** (bool): Flag to use GPU if available,
            default is True. **pointwise** (bool): Flag to evaluate charge
            pointwise on voxels rather than average, default is False.

        Returns
        -------
        ndarray
            Diffraction data to be interpreted as a discretisation on the original
            detector mesh.

        """

        species = structure.element
        coordinates = structure.xyz_cartn.reshape(species.size, -1)
        dim = coordinates.shape[1]  # guarenteed to be 3

        if not ZERO > 0:
            raise ValueError("The value of the ZERO argument must be greater than 0")

        if probe_centre is None:
            probe_centre = np.zeros(dim)
        elif len(probe_centre) == (dim - 1):
            probe_centre = np.array(list(probe_centre) + [0])

        coordinates = coordinates - probe_centre[None]

        if not precessed:
            precessed = (float(0), 1)
        elif np.isscalar(precessed):
            precessed = (float(precessed), 30)

        dtype = np.dtype(dtype)
        dtype = round(dtype.itemsize / (1 if dtype.kind == "f" else 2))
        dtype = "f" + str(dtype), "c" + str(2 * dtype)

        # Filter list of atoms
        for d in range(dim - 1):
            ind = coordinates[:, d] >= self.detector[d].min() - 20
            coordinates, species = coordinates[ind, :], species[ind]
            ind = coordinates[:, d] <= self.detector[d].max() + 20
            coordinates, species = coordinates[ind, :], species[ind]

        # Add z-coordinate
        z_range = max(
            z_range, coordinates[:, -1].ptp()
        )  # enforce minimal resolution in reciprocal space
        x = [
            self.detector[0],
            self.detector[1],
            np.arange(
                coordinates[:, -1].min() - 20,
                coordinates[:, -1].min() + z_range + 20,
                slice_thickness,
            ),
        ]

        if mode == "kinematic":
            from diffsims.utils import kinematic_simulation_utils as simlib
        else:
            raise NotImplementedError(
                "<mode> = %s is not currently supported" % repr(mode)
            )

        kwargs["dtype"] = dtype
        kwargs["ZERO"] = ZERO
        return simlib.get_diffraction_image(
            coordinates, species, probe, x, self.wavelength, precessed, **kwargs
        )