Exemple #1
0
def scatteringdata(elem, e1, e2, de, fname):
    en_array = energy_array(e1, e2, de)
    mu_total = xraydb.mu_elam(elem, en_array, kind='total')
    mu_photo = xraydb.mu_elam(elem, en_array, kind='photo')
    mu_incoh = xraydb.mu_elam(elem, en_array, kind='incoh')
    mu_coher = xraydb.mu_elam(elem, en_array, kind='coh')

    header = [
        ' X-ray Atomic Scattering Cross-Sections from xrayweb  %s ' %
        time.ctime(),
        ' Element : %s ' % elem, ' Column.1: Energy (eV)',
        ' Column.2: mu_total (cm^2/gr)',
        ' Column.3: mu_photo (cm^2/gr)  # Photo-electric',
        ' Column.4: mu_coher (cm^2/gr)  # Rayleigh',
        ' Column.5: mu_incoh (cm^2/gr)  # Compton'
    ]

    arr_names = [
        'energy       ', 'mu_total     ', 'mu_photo     ', 'mu_coher     ',
        'mu_incoh     '
    ]

    arrays = [en_array, mu_total, mu_photo, mu_coher, mu_incoh]

    atz = xraydb.atomic_number(elem)
    if atz < 93:
        header.extend([
            ' Column.6: f1 (electrons/atom) # real resonant',
            ' Column.7: f2 (electrons/atom) # imag resonant'
        ])

        arr_names.extend(['f1           ', 'f2           '])
        arrays.extend([
            xraydb.f1_chantler(elem, en_array),
            xraydb.f2_chantler(elem, en_array)
        ])

    txt = make_asciifile(header, arr_names, arrays)
    return Response(txt, mimetype='text/plain')
Exemple #2
0
def test_f1f2_chantler():
    en = np.linspace(10000, 15000, 51)

    f1 = np.array([-5.97, -6.08, -6.20, -6.33, -6.46, -6.60, -6.75, -6.91,
                   -7.09, -7.28, -7.49, -7.72, -7.99, -8.28, -8.64, -9.06,
                   -9.60, -10.33, -11.54, -15.14, -12.27, -10.64, -9.78,
                   -9.18, -8.76, -8.43, -8.18, -7.98, -7.83, -7.73, -7.66,
                   -7.64, -7.66, -7.73, -7.87, -8.13, -8.58, -9.91, -9.18,
                   -8.19, -7.73, -7.46, -7.36, -7.61, -7.43, -6.61, -6.13,
                   -5.77, -5.46, -5.20, -4.96 ])

    f2 = np.array([5.12, 5.04, 4.96, 4.87, 4.80, 4.72, 4.64, 4.57, 4.50,
                   4.43, 4.37, 4.30, 4.24, 4.18, 4.12, 4.06, 4.01, 3.97,
                   3.93, 4.15, 9.94, 9.83, 9.70, 9.57, 9.43, 9.30, 9.17,
                   9.05, 8.92, 8.80, 8.69, 8.57, 8.46, 8.35, 8.25, 8.14,
                   8.05, 8.02, 10.94, 10.83, 10.71, 10.59, 10.47, 10.39,
                   11.75, 11.67, 11.56, 11.44, 11.33, 11.21, 11.10])


    assert_allclose(f1, f1_chantler('Au', en), rtol=0.01)
    assert_allclose(f2, f2_chantler('Au', en), rtol=0.01)
    assert_allclose(f1, chantler_data('Au', en, 'f1'), rtol=0.01)
    assert_allclose(f2, chantler_data('Au', en, 'f2'), rtol=0.01)
Exemple #3
0
def test_f1f2_chantler_mo():
    en = np.linspace(1000, 500000, 501)
    f1 = f1_chantler('Mo', en)
    assert (len(f1) > 400)
Exemple #4
0
def scattering(elem=None, e1='1000', e2='50000', de='50'):
    f1f2_plot = mu_plot = {}
    if len(request.form) != 0:
        elem = request.form.get('elem', 'None')
        e1 = request.form.get('e1', e1)
        e2 = request.form.get('e2', e2)
        de = request.form.get('de', de)

    if elem not in (None, 'None', ''):
        atz = xraydb.atomic_number(elem)
        en_array = energy_array(e1, e2, de)
        mu_total = xraydb.mu_elam(elem, en_array, kind='total')
        mu_photo = xraydb.mu_elam(elem, en_array, kind='photo')
        mu_incoh = xraydb.mu_elam(elem, en_array, kind='incoh')
        mu_coher = xraydb.mu_elam(elem, en_array, kind='coh')
        yrange = [
            -0.25 + min(-1.8, np.log10(mu_photo.min() + 1.e-5),
                        np.log10(mu_incoh.min() + 1.e-5),
                        np.log10(mu_coher.min() + 1.e-5)),
            0.75 + np.log10(mu_total.max() + 1.e-5)
        ]

        mu_plot = make_plot(en_array,
                            mu_total,
                            'Mass Attenuation for %s' % elem,
                            elem,
                            ytitle='mu/rho (cm^2/gr)',
                            xtitle='Energy (eV)',
                            xlog_scale=False,
                            ylog_scale=True,
                            yrange=yrange,
                            yformat='.2f',
                            y1label='Total',
                            y2=mu_photo,
                            y2label='Photo-electric',
                            y3=mu_incoh,
                            y3label='Incoherent',
                            y4=mu_coher,
                            y4label='Coherent')
        if atz < 93:
            try:
                f1 = xraydb.f1_chantler(elem, en_array)
            except:
                f1 = xraydb.f1_chantler(elem, en_array, smoothing=1)

            f2 = xraydb.f2_chantler(elem, en_array)
            f1f2_plot = make_plot(en_array,
                                  f1,
                                  'Resonant Scattering factors for %s' % elem,
                                  elem,
                                  ytitle='f1, f2 (electrons/atom)',
                                  xtitle='Energy (eV)',
                                  xlog_scale=False,
                                  ylog_scale=False,
                                  y2=f2,
                                  y1label='f1',
                                  y2label='f2')
    return render_template('scattering.html',
                           elem=elem,
                           e1=e1,
                           e2=e2,
                           de=int(de),
                           f1f2_plot=f1f2_plot,
                           mu_plot=mu_plot,
                           materials_dict=materials_dict)
Exemple #5
0
def mback(energy, mu=None, group=None, z=None, edge='K', e0=None, pre1=None, pre2=-50,
          norm1=100, norm2=None, order=3, leexiang=False, tables='chantler', fit_erfc=False,
          return_f1=False, _larch=None):
    """
    Match mu(E) data for tabulated f''(E) using the MBACK algorithm and,
    optionally, the Lee & Xiang extension

    Arguments
    ----------
      energy:     array of x-ray energies, in eV.
      mu:         array of mu(E).
      group:      output group.
	  z:          atomic number of the absorber.
	  edge:       x-ray absorption edge (default 'K')
      e0:         edge energy, in eV.  If None, it will be determined here.
      pre1:       low E range (relative to e0) for pre-edge region.
      pre2:       high E range (relative to e0) for pre-edge region.
      norm1:      low E range (relative to e0) for post-edge region.
      norm2:      high E range (relative to e0) for post-edge region.
      order:      order of the legendre polynomial for normalization.
	              (default=3, min=0, max=5).
      leexiang:   boolean (default False)  to use the Lee & Xiang extension.
      tables:     tabulated scattering factors: 'chantler' [deprecated]
      fit_erfc:   boolean (default False) to fit parameters of error function.
      return_f1:  boolean (default False) to include the f1 array in the group.


    Returns
    -------
      None

    The following attributes will be written to the output group:
      group.f2:            tabulated f2(E).
      group.f1:            tabulated f1(E) (if 'return_f1' is True).
      group.fpp:           mback atched spectrum.
	  group.edge_step:     edge step of spectrum.
	  group.norm:          normalized spectrum.
      group.mback_params:  group of parameters for the minimization.

    Notes:
        Chantler tables is now used, with Cromer-Liberman no longer supported.
    References:
      * MBACK (Weng, Waldo, Penner-Hahn): http://dx.doi.org/10.1086/303711
      * Lee and Xiang: http://dx.doi.org/10.1088/0004-637X/702/2/970
      * Cromer-Liberman: http://dx.doi.org/10.1063/1.1674266
      * Chantler: http://dx.doi.org/10.1063/1.555974
    """
    order = max(min(order, MAXORDER), 0)

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

    energy = remove_dups(energy)
    if e0 is None or e0 < energy[1] or e0 > energy[-2]:
        e0 = find_e0(energy, mu, group=group)

    print(e0)
    ie0 = index_nearest(energy, e0)
    e0 = energy[ie0]

    pre1_input = pre1
    norm2_input = norm2

    if pre1 is None:  pre1  = min(energy) - e0
    if norm2 is None: norm2 = max(energy) - e0
    if norm2 < 0:     norm2 = max(energy) - e0 - norm2
    pre1  = max(pre1,  (min(energy) - e0))
    norm2 = min(norm2, (max(energy) - e0))

    if pre1 > pre2:
        pre1, pre2 = pre2, pre1
    if norm1 > norm2:
        norm1, norm2 = norm2, norm1

    p1 = index_of(energy, pre1+e0)
    p2 = index_nearest(energy, pre2+e0)
    n1 = index_nearest(energy, norm1+e0)
    n2 = index_of(energy, norm2+e0)
    if p2 - p1 < 2:
        p2 = min(len(energy), p1 + 2)
    if n2 - n1 < 2:
        p2 = min(len(energy), p1 + 2)

    ## theta is a boolean array indicating the
	## energy values considered for the fit.
    ## theta=1 for included values, theta=0 for excluded values.
    theta            = np.zeros_like(energy, dtype='int')
    theta[p1:(p2+1)] = 1
    theta[n1:(n2+1)] = 1

    ## weights for the pre- and post-edge regions, as defined in the MBACK paper (?)
    weight            = np.ones_like(energy, dtype=float)
    weight[p1:(p2+1)] = np.sqrt(np.sum(weight[p1:(p2+1)]))
    weight[n1:(n2+1)] = np.sqrt(np.sum(weight[n1:(n2+1)]))

    ## get the f'' function from CL or Chantler
    f1 = f1_chantler(z, energy)
    f2 = f2_chantler(z, energy)
    group.f2 = f2
    if return_f1:
        group.f1 = f1

    em = find_xray_line(z, edge).energy # erfc centroid

    params = Parameters()
    params.add(name='s',  value=1.0,  vary=True)  # scale of data
    params.add(name='xi', value=50.0, vary=False, min=0) # width of erfc
    params.add(name='a',  value=0.0, vary=False)  # amplitude of erfc
    if fit_erfc:
        params['a'].vary  = True
        params['a'].value = 0.5
        params['xi'].vary  = True

    for i in range(order+1): # polynomial coefficients
        params.add(name='c%d' % i, value=0, vary=True)

    out = minimize(match_f2, 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, f2=f2, e0=e0, em=em,
                              order=order, weight=weight, theta=theta, leexiang=leexiang))

    opars = out.params.valuesdict()
    eoff = energy - e0

    norm_function = opars['a']*erfc((energy-em)/opars['xi']) + opars['c0']
    for i in range(order):
        attr = 'c%d' % (i + 1)
        if attr in opars:
            norm_function  += opars[attr]* eoff**(i + 1)

    group.e0 = e0
    group.fpp = opars['s']*mu - norm_function
    # calculate edge step and normalization from f2 + norm_function
    pre_f2 = preedge(energy, group.f2+norm_function, e0=e0, pre1=pre1,
	         pre2=pre2, norm1=norm1, norm2=norm2, nnorm=2, nvict=0)
    group.edge_step = pre_f2['edge_step'] / opars['s']
    group.norm = (opars['s']*mu -  pre_f2['pre_edge']) / pre_f2['edge_step']
    group.mback_details = Group(params=opars, pre_f2=pre_f2,
                                f2_scaled=opars['s']*f2,
                                norm_function=norm_function)