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)
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)