コード例 #1
0
ファイル: run_test.py プロジェクト: tschoonj/conda-recipes
def test_edge_energies():
    from xraydb.xray import _edge_energies

    assert xray_edge(30, 'K') == xray_edge('Zn', 'K')

    for edge in ('k', 'l3', 'l2'):
        for iz in range(1, 98):
            _edge = xray_edge(iz, edge)
            if _edge is not None:
                en = _edge.energy
                assert _edge_energies[edge][iz] < en + 0.5
                assert _edge_energies[edge][iz] > en - 0.5

    assert_allclose(xray_edge('Zn', 'K', energy_only=True), 9660, rtol=0.01)

    sr_edges = xray_edges('Sr')

    assert_allclose(sr_edges['K'].energy, 16105.0,  rtol=0.001)
    assert_allclose(sr_edges['L1'].energy, 2216.0, rtol=0.001)
    assert_allclose(sr_edges['L2'].energy, 2007.0, rtol=0.001)
    assert_allclose(sr_edges['L3'].energy, 1940.0, rtol=0.001)
    assert_allclose(sr_edges['M1'].energy, 358.7, rtol=0.001)
    assert_allclose(sr_edges['M2'].energy, 280.3, rtol=0.001)
    assert_allclose(sr_edges['M3'].energy, 270.0, rtol=0.001)
    assert_allclose(sr_edges['M4'].energy, 136.0, rtol=0.001)
    assert_allclose(sr_edges['M5'].energy, 134.2, rtol=0.001)
    assert_allclose(sr_edges['N1'].energy, 38.9, rtol=0.001)
    assert_allclose(sr_edges['N2'].energy, 21.6, rtol=0.001)
    assert_allclose(sr_edges['N3'].energy, 20.1, rtol=0.001)


    assert_allclose(sr_edges['K'].fyield, 0.664652, rtol=0.001)
    assert_allclose(sr_edges['L1'].fyield, 0.0051, rtol=0.001)
    assert_allclose(sr_edges['L2'].fyield, 0.024, rtol=0.001)
    assert_allclose(sr_edges['L3'].fyield, 0.026, rtol=0.001)
    assert_allclose(sr_edges['M1'].fyield, 5.95e-05, rtol=0.001)
    assert_allclose(sr_edges['M2'].fyield, 3.7e-05, rtol=0.001)
    assert_allclose(sr_edges['M3'].fyield, 0.000105, rtol=0.001)
    assert_allclose(sr_edges['M4'].fyield, 0.0027, rtol=0.001)
    assert_allclose(sr_edges['M5'].fyield, 0.0, rtol=0.001)
    assert_allclose(sr_edges['N1'].fyield, 1.2e-05, rtol=0.001)
    assert_allclose(sr_edges['N2'].fyield, 0.013, rtol=0.001)
    assert_allclose(sr_edges['N3'].fyield, 0.013, rtol=0.001)


    assert_allclose(sr_edges['K'].jump_ratio, 6.888, rtol=0.01)
    assert_allclose(sr_edges['L1'].jump_ratio, 1.1415, rtol=0.01)
    assert_allclose(sr_edges['L2'].jump_ratio, 1.4, rtol=0.01)
    assert_allclose(sr_edges['L3'].jump_ratio, 3.982, rtol=0.01)
    assert_allclose(sr_edges['M1'].jump_ratio, 1.04, rtol=0.01)
    assert_allclose(sr_edges['M2'].jump_ratio, 1.058, rtol=0.01)
    assert_allclose(sr_edges['M3'].jump_ratio, 1.12491, rtol=0.01)
    assert_allclose(sr_edges['M4'].jump_ratio, 1.139, rtol=0.01)
    assert_allclose(sr_edges['M5'].jump_ratio, 1.808, rtol=0.01)
    assert_allclose(sr_edges['N1'].jump_ratio, 1.0, rtol=0.01)
    assert_allclose(sr_edges['N2'].jump_ratio, 1.0, rtol=0.01)
    assert_allclose(sr_edges['N3'].jump_ratio, 1.0, rtol=0.01)
コード例 #2
0
ファイル: mca.py プロジェクト: yevgenyr/xraylarch
    def predict_escape(self, det='Si', scale=1.0):
        """
        predict detector escape for a spectrum, save to 'escape' attribute

        X-rays penetrate a depth 1/mu(material, energy) and the
        detector fluorescence escapes from that depth as
            exp(-mu(material, KaEnergy)*thickness)
        with a fluorecence yield of the material

        """
        fluor_en = xray_line(det, 'Ka').energy / 1000.0
        edge = xray_edge(det, 'K')

        # here we use the 1/e depth for the emission
        # and the 1/e depth of the incident beam:
        # the detector fluorescence can escape on either side
        mu_emit = material_mu(det, fluor_en * 1000)
        mu_input = material_mu(det, self.energy * 1000)
        escape = 0.5 * scale * edge.fyield * np.exp(-mu_emit / (2 * mu_input))
        escape[np.where(self.energy * 1000 < edge.energy)] = 0.0
        escape *= interp(self.energy - fluor_en,
                         self.counts * 1.0,
                         self.energy,
                         kind='cubic')
        self.escape = escape
コード例 #3
0
 def read_energy_label(self):
     label_text = self.lineEdit_energy.text()
     try:
         energy = float(label_text)
     except ValueError:
         element, edge = label_text.split('-')
         energy = xraydb.xray_edge(element, edge).energy
         self.lineEdit_energy.setText(str(int(energy)))
     return energy
コード例 #4
0
def fluo_corr(norm, formula, elem, edge, line, anginp, angout):
    """
    Correct over-absorption (self-absorption) for fluorescene XAFS
    using the based on the `larch` implementation of the FLUO alogrithm of
    D. Haskel. See FLUO manual_ for details.

    .. _manual: https://www3.aps.anl.gov/haskel/fluo.html

    Parameters
    ----------
    norm : iter
        Normalized fluorescence
    formula : str
        Chemical formula of the compound. For example: 'EuO'.
    elem : str
        Element of interest. For example: 'Eu'.
    edge : str
        Absorption edge of interest. For example: 'L3'.
    line : str
        Fluorescence line measured. For example: 'La'.
    anginp : float
        Input angle with respect to the sample surface. See FLUO manual.
    anginp : float
        Output angle with respect to the sample surface. See FLUO manual.

    Returns
    --------
    norm_corr : numpy.array
        Corrected normalized fluorescence.
    """

    # Angular correction. Avoid divide by zero.
    ang_corr = (np.sin(np.deg2rad(anginp)) /
                np.sin(max(1.e-7, np.deg2rad(angout))))

    # Find edge energies and fluorescence line energy
    e_edge = xray_edge(elem, edge).energy
    e_fluor = xray_line(elem, line).energy

    # Calculate mu(E) for fluorescence energy, above, below edge
    # alpha ends up independent of density!
    muvals = material_mu(formula,
                         np.array([e_fluor, e_edge - 10.0, e_edge + 10.0]),
                         density=1)

    # Do the correction
    alpha = (muvals[0] * ang_corr + muvals[1]) / (muvals[2] - muvals[1])
    norm_corr = np.array(norm) * alpha / (alpha + 1 - np.array(norm))

    return norm_corr
コード例 #5
0
ファイル: xrf_model.py プロジェクト: yevgenyr/xraylarch
    def calc_escape_scale(self, energy, thickness=None):
        """
        calculate energy dependence of escape effect

        X-rays penetrate a depth 1/mu(material, energy) and the
        detector fluorescence escapes from that depth as
            exp(-mu(material, KaEnergy)*thickness)
        with a fluorecence yield of the material

        """
        det = self.detector
        # note material_mu, xray_edge, xray_line work in eV!
        escape_energy_ev = xray_line(det.material, 'Ka').energy
        mu_emit = material_mu(det.material, escape_energy_ev)
        self.escape_energy = 0.001 * escape_energy_ev

        mu_input = material_mu(det.material, 1000 * energy)

        edge = xray_edge(det.material, 'K')
        self.escape_scale = edge.fyield * np.exp(-mu_emit / (2 * mu_input))
        self.escape_scale[np.where(energy < 0.001 * edge.energy)] = 0.0
コード例 #6
0
def fluo_corr(energy,
              mu,
              formula,
              elem,
              group=None,
              edge='K',
              anginp=45,
              angout=45,
              _larch=None,
              **pre_kws):
    """correct over-absorption (self-absorption) for fluorescene XAFS
    using the FLUO alogrithm of D. Haskel.

    Arguments
    ---------
      energy    array of energies
      mu        uncorrected fluorescence mu
      formula   string for sample stoichiometry
      elem      atomic symbol or Z of absorbing element
      group     output group [default None]
      edge      name of edge ('K', 'L3', ...) [default 'K']
      anginp    input angle in degrees  [default 45]
      angout    output angle in degrees  [default 45]

    Additional keywords will be passed to pre_edge(), which will be used
    to ensure consistent normalization.

    Returns
    --------
       None, writes `mu_corr` and `norm_corr` (normalized `mu_corr`)
       to output group.

    Notes
    -----
       Support First Argument Group convention, requiring group
       members 'energy' and 'mu'
    """
    energy, mu, group = parse_group_args(energy,
                                         members=('energy', 'mu'),
                                         defaults=(mu, ),
                                         group=group,
                                         fcn_name='fluo_corr')
    # gather pre-edge options
    pre_opts = {
        'e0': None,
        'nnorm': 1,
        'nvict': 0,
        'pre1': None,
        'pre2': -30,
        'norm1': 100,
        'norm2': None
    }
    if hasattr(group, 'pre_edge_details'):
        uopts = getattr(group.pre_edge_details, 'call_args', {})
        for attr in pre_opts:
            if attr in uopts:
                pre_opts[attr] = uopts[attr]
    pre_opts.update(pre_kws)
    pre_opts['step'] = None
    pre_opts['nvict'] = 0

    # generate normalized mu for correction
    preinp = preedge(energy, mu, **pre_opts)

    ang_corr = (np.sin(max(1.e-7, np.deg2rad(anginp))) /
                np.sin(max(1.e-7, np.deg2rad(angout))))

    # find edge energies and fluorescence line energy
    e_edge = xray_edge(elem, edge).energy
    e_fluor = xray_line(elem, edge).energy

    # calculate mu(E) for fluorescence energy, above, below edge

    muvals = material_mu(formula,
                         np.array([e_fluor, e_edge - 10.0, e_edge + 10.0]),
                         density=1)

    alpha = (muvals[0] * ang_corr + muvals[1]) / (muvals[2] - muvals[1])
    mu_corr = mu * alpha / (alpha + 1 - preinp['norm'])
    preout = preedge(energy, mu_corr, **pre_opts)
    if group is not None:
        if _larch is not None:
            group = set_xafsGroup(group, _larch=_larch)
        group.mu_corr = mu_corr
        group.norm_corr = preout['norm']
コード例 #7
0
def mback_norm(energy, mu=None, group=None, z=None, edge='K', e0=None,
               pre1=None, pre2=None, norm1=None, norm2=None, nnorm=None, nvict=1,
               _larch=None):
    """
    simplified version of MBACK to Match mu(E) data for tabulated f''(E)
    for normalization

    Arguments:
      energy, mu:  arrays of energy and mu(E)
      group:       output group (and input group for e0)
      z:           Z number of absorber
      e0:          edge energy
      pre1:        low E range (relative to E0) for pre-edge fit
      pre2:        high E range (relative to E0) for pre-edge fit
      norm1:       low E range (relative to E0) for post-edge fit
      norm2:       high E range (relative to E0) for post-edge fit
      nnorm:       degree of polynomial (ie, nnorm+1 coefficients will be
                   found) for post-edge normalization curve fit to the
                   scaled f2. Default=1 (linear)

    Returns:
      group.norm_poly:     normalized mu(E) from pre_edge()
      group.norm:          normalized mu(E) from this method
      group.mback_mu:      tabulated f2 scaled and pre_edge added to match mu(E)
      group.mback_params:  Group of parameters for the minimization

    References:
      * MBACK (Weng, Waldo, Penner-Hahn): http://dx.doi.org/10.1086/303711
      * Chantler: http://dx.doi.org/10.1063/1.555974
    """
    ### implement the First Argument Group convention
    energy, mu, group = parse_group_args(energy, members=('energy', 'mu'),
                                         defaults=(mu,), group=group,
                                         fcn_name='mback')
    if len(energy.shape) > 1:
        energy = energy.squeeze()
    if len(mu.shape) > 1:
        mu = mu.squeeze()

    if _larch is not None:
        group = set_xafsGroup(group, _larch=_larch)
    group.norm_poly = group.norm*1.0

    if z is not None:              # need to run find_e0:
        e0_nominal = xray_edge(z, edge).energy
    if e0 is None:
        e0 = getattr(group, 'e0', None)
        if e0 is None:
            find_e0(energy, mu, group=group)
            e0 = group.e0

    atsym = None
    if z is None or z < 2:
        atsym, edge = guess_edge(group.e0)
        z = atomic_number(atsym)
    if atsym is None and z is not None:
        atsym = atomic_symbol(z)

    if getattr(group, 'pre_edge_details', None) is None:  # pre_edge never run
        preedge(energy, mu, pre1=pre1, pre2=pre2, nvict=nvict,
                norm1=norm1, norm2=norm2, e0=e0, nnorm=nnorm)

    mu_pre = mu - group.pre_edge
    f2 = f2_chantler(z, energy)

    weights = np.ones(len(energy))*1.0

    if norm2 is None:
        norm2 = max(energy) - e0

    if norm2 < 0:
        norm2 = max(energy) - e0  - norm2

    # avoid l2 and higher edges
    if edge.lower().startswith('l'):
        if edge.lower() == 'l3':
            e_l2 = xray_edge(z, 'L2').energy
            norm2 = min(norm2,  e_l2-e0)
        elif edge.lower() == 'l2':
            e_l2 = xray_edge(z, 'L1').energy
            norm2 = min(norm2,  e_l1-e0)

    ipre2 = index_of(energy, e0+pre2)
    inor1 = index_of(energy, e0+norm1)
    inor2 = index_of(energy, e0+norm2) + 1


    weights[ipre2:] = 0.0
    weights[inor1:inor2] = np.linspace(0.1, 1.0, inor2-inor1)

    params = Parameters()
    params.add(name='slope',   value=0.0,    vary=True)
    params.add(name='offset',  value=-f2[0], vary=True)
    params.add(name='scale',   value=f2[-1], vary=True)

    out = minimize(f2norm, params, method='leastsq',
                   gtol=1.e-5, ftol=1.e-5, xtol=1.e-5, epsfcn=1.e-5,
                   kws = dict(en=energy, mu=mu_pre, f2=f2, weights=weights))

    p = out.params.valuesdict()

    model = (p['offset'] + p['slope']*energy + f2) * p['scale']

    group.mback_mu = model + group.pre_edge

    pre_f2 = preedge(energy, model, nnorm=nnorm, nvict=nvict, e0=e0,
                     pre1=pre1, pre2=pre2, norm1=norm1, norm2=norm2)

    step_new = pre_f2['edge_step']

    group.edge_step_poly  = group.edge_step
    group.edge_step_mback = step_new
    group.norm_mback = mu_pre / step_new


    group.mback_params = Group(e0=e0, pre1=pre1, pre2=pre2, norm1=norm1,
                               norm2=norm2, nnorm=nnorm, fit_params=p,
                               fit_weights=weights, model=model, f2=f2,
                               pre_f2=pre_f2, atsym=atsym, edge=edge)

    if (abs(step_new - group.edge_step)/(1.e-13+group.edge_step)) > 0.75:
        print("Warning: mback edge step failed....")
    else:
        group.edge_step = step_new
        group.norm       = group.norm_mback