Example #1
0
def test_core_width():
    kwid_known = np.array([
        0.0201, 0.0269, 0.036, 0.0483, 0.0647, 0.0868, 0.1163, 0.1559, 0.2089,
        0.24, 0.3, 0.36, 0.42, 0.48, 0.53, 0.59, 0.64, 0.68, 0.74, 0.81, 0.86,
        0.94, 1.01, 1.08, 1.16, 1.25, 1.33, 1.44, 1.55, 1.67, 1.82, 1.96, 2.14,
        2.33, 2.52, 2.75, 2.99, 3.25, 3.52, 3.84, 4.14, 4.52, 4.91, 5.33, 5.77,
        6.24, 6.75, 7.28, 7.91, 8.49, 9.16, 9.89, 10.6, 11.4, 12.3, 13.2, 14.1,
        15.1, 16.2, 17.3, 18.5, 19.7, 21.0, 22.3, 23.8, 25.2, 26.8, 28.4, 30.1,
        31.9, 33.7, 35.7, 37.7, 39.9, 42.1, 44.4, 46.8, 49.3, 52.0, 54.6, 57.4,
        60.4, 63.4, 66.6, 69.8, 73.3, 76.8, 80.4, 84.1, 88.0, 91.9, 96.1,
        100.0, 105.0, 109.0, 114.0, 119.0, 124.0
    ])

    kwid = np.array([core_width(i, 'K') for i in range(1, 99)])

    assert_allclose(kwid, kwid_known, rtol=0.01)

    l3wid_known = np.array([
        0.17, 0.19, 0.22, 0.24, 0.27, 0.32, 0.36, 0.43, 0.48, 0.56, 0.65, 0.76,
        0.82, 0.94, 1.0, 1.08, 1.17, 1.27, 1.39, 1.5, 1.57, 1.66, 1.78, 1.91,
        2.0, 2.13, 2.25, 2.4, 2.5, 2.65, 2.75, 2.87, 2.95, 3.08, 3.13, 3.25,
        3.32, 3.41, 3.48, 3.6, 3.65, 3.75, 3.86, 3.91, 4.01, 4.12, 4.17, 4.26,
        4.35, 4.48, 4.6, 4.68, 4.8, 4.88, 4.98, 5.04, 5.16, 5.25, 5.31, 5.41,
        5.5, 5.65, 5.81, 5.98, 6.13, 6.29, 6.41, 6.65, 6.82, 6.98, 7.13, 7.33,
        7.43, 7.59, 7.82, 8.04, 8.26, 8.55, 8.75
    ])
    l3wid = np.array([core_width(i, 'L3') for i in range(20, 99)])
    assert_allclose(l3wid, l3wid_known, rtol=0.01)
Example #2
0
def f1f2(z, energies, width=None, edge=None):
    """Return anomalous scattering factors f1, f2 from Cromer-Liberman

    Look-up and return f1, f2 for an element and array of energies
    from Cromer-Liberman (Cowan-Brennan implementation)

    Parameters
    ----------
    z:         atomic number of element
    energies:  array of x-ray energies (in eV)
    width:     width used to convolve values with lorentzian profile
    edge:      x-ray edge ('K', 'L3', etc) used to lookup energy
               width for convolution.

    Returns:
    ---------
    f1, f2:    anomalous scattering factors

    """
    global CLLIB
    if CLLIB is None:
        CLLIB = get_dll('cldata')

    en = as_ndarray(energies)

    if not isinstance(z, int):
        z  = atomic_number(z)
        if z is None:
            return None

    if z > 92:
        print( 'Cromer-Liberman data not available for Z>92')
        return

    if edge is not None or width is not None:
        natwid = core_width(element=z, edge=edge)
        if width is None and natwid not in (None, []):
            width = natwid

    if width is not None: # will convolve!
        e_extra = int(width*80.0)
        estep = (en[1:] - en[:-1]).min()
        emin = min(en) - e_extra
        emax = max(en) + e_extra

        npts = 1 + abs(emax-emin+estep*0.02)/abs(estep)
        en   = np.linspace(emin, emax, int(npts))
        nk   = int(e_extra / estep)
        sig  = width/2.0
        lor  = (1./(1 + ((np.arange(2*nk+1)-nk*1.0)/sig)**2))/(np.pi*sig)
        scale = lor.sum()

    # create ctypes pointers for the C function
    npts   = len(en)
    p_z    = ctypes.pointer(ctypes.c_int(int(z)))
    p_npts = ctypes.pointer(ctypes.c_int(npts))
    p_en   = (npts*ctypes.c_double)()
    p_f1   = (npts*ctypes.c_double)()
    p_f2   = (npts*ctypes.c_double)()

    for i in range(npts):
        p_en[i] = en[i]

    nout = CLLIB.f1f2(p_z, p_npts, p_en, p_f1, p_f2)
    f1 = np.array([i for i in p_f1[:]])
    f2 = np.array([i for i in p_f2[:]])
    if width is not None: # do the convolution
        f1 = np.interp(energies, en, convolve(f1, lor)[nk:-nk])/scale
        f2 = np.interp(energies, en, convolve(f2, lor)[nk:-nk])/scale
    return (f1, f2)