コード例 #1
0
def test_fast_abs(shape, n):
    x = _random_array(shape, n)
    y = np.empty(shape, dtype=x.dtype)
    z = fast_abs(x, y)

    np.testing.assert_allclose(abs(x), fast_abs(x), 1e-5)
    np.testing.assert_allclose(abs(x), y, 1e-5)
    assert y is z
コード例 #2
0
def get_diffraction_image(coordinates,
                          species,
                          probe,
                          x,
                          wavelength,
                          precession,
                          GPU=True,
                          pointwise=False,
                          **kwargs):
    """
    Return kinematically simulated diffraction pattern

    Parameters
    ----------
    coordinates : `numpy.ndarray` [`float`],  (n_atoms, 3)
        List of atomic coordinates
    species : `numpy.ndarray` [`int`],  (n_atoms,)
        List of atomic numbers
    probe : `diffsims.ProbeFunction`
        Function representing 3D shape of beam
    x : `list` [`numpy.ndarray` [`float`] ], of shapes [(nx,), (ny,), (nz,)]
        Mesh on which to compute the volume density
    wavelength : `float`
        Wavelength of electron beam
    precession : a pair (`float`, `int`)
        The float dictates the angle of precession and the int how many points are
        used to discretise the integration.
    dtype : (`str`, `str`)
        tuple of floating/complex datatypes to cast outputs to
    ZERO : `float` > 0, optional
        Rounding error permitted in computation of atomic density. This value is
        the smallest value rounded to 0.
    GPU : `bool`, optional
        Flag whether to use GPU or CPU discretisation. Default (if available) is True
    pointwise : `bool`, optional
        Optional parameter whether atomic intensities are computed point-wise at
        the centre of a voxel or an integral over the voxel. default=False

    Returns
    -------
    DP : `numpy.ndarray` [`dtype[0]`], (nx, ny, nz)
        The two-dimensional diffraction pattern evaluated on the reciprocal grid
        corresponding to the first two vectors of `x`.
    """
    FTYPE = kwargs["dtype"][0]
    kwargs["GPU"] = GPU
    kwargs["pointwise"] = pointwise

    x = [X.astype(FTYPE, copy=False) for X in x]
    y = to_recip(x)
    if wavelength == 0:
        p = probe(x).mean(-1)
        vol = get_discretisation(coordinates, species, x[:2], **kwargs)[..., 0]
        ft = get_DFT(x[:-1], y[:-1])[0]
    else:
        p = probe(x)
        vol = get_discretisation(coordinates, species, x, **kwargs)
        ft = get_DFT(x, y)[0]

    if precession[0] == 0:
        arr = ft(vol * p)
        arr = fast_abs(arr, arr).real**2
        if wavelength == 0:
            return normalise(arr)
        else:
            return normalise(grid2sphere(arr, y, None, 2 * pi / wavelength))

    R = [
        precess_mat(precession[0], i * 360 / precession[1])
        for i in range(precession[1])
    ]

    if wavelength == 0:
        return normalise(
            sum(
                get_diffraction_image(coordinates.dot(r), species, probe, x,
                                      wavelength, (0, 1), **kwargs)
                for r in R))

    fftshift_phase(vol)  # removes need for fftshift after fft
    buf = empty(vol.shape, dtype=FTYPE)
    ft, buf = plan_fft(buf, overwrite=True, planner=1)
    DP = None
    for r in R:
        probe(to_mesh(x, r.T, dtype=FTYPE), out=buf,
              scale=vol)  # buf = bess*vol

        # Do convolution
        newFT = ft()
        newFT = fast_abs(newFT, buf).real
        newFT *= newFT  # newFT = abs(newFT) ** 2
        newFT = grid2sphere(newFT.real, y, list(r), 2 * pi / wavelength)

        if DP is None:
            DP = newFT
        else:
            DP += newFT

    return normalise(DP.astype(FTYPE, copy=False))