예제 #1
0
파일: test_xray.py 프로젝트: mlevant/XrayDB
def test_atomic_data():
    assert atomic_number('zn') == 30
    assert atomic_symbol(26) == 'Fe'
    assert atomic_mass(45) > 102.8
    assert atomic_mass(45) < 103.0
    assert atomic_density(29) == atomic_density('cu')
    assert atomic_density(22) > 4.51
예제 #2
0
def element(elem=None):
    edges = atomic = lines = {}
    if elem is not None:
        atomic = {
            'n': xraydb.atomic_number(elem),
            'mass': xraydb.atomic_mass(elem),
            'density': xraydb.atomic_density(elem)
        }
        _edges = xraydb.xray_edges(elem)
        _lines = xraydb.xray_lines(elem)
        lines = OrderedDict()
        for k in sorted(_lines.keys()):
            en, inten, init, final = _lines[k]  # XrayLine
            lines[k] = XrayLine(energy=f'{en:.1f}',
                                intensity=f'{inten:.5f}',
                                initial_level=init,
                                final_level=final)
        edges = OrderedDict()
        for k in sorted(_edges.keys()):
            en, fy, jump = _edges[k]  # XrayEdge
            edges[k] = XrayEdge(energy=f'{en:.1f}',
                                fyield=f'{fy:.5f}',
                                jump_ratio=f'{jump:.3f}')

    return render_template('elements.html',
                           edges=edges,
                           elem=elem,
                           atomic=atomic,
                           lines=lines,
                           materials_dict=materials_dict)
예제 #3
0
파일: webapp.py 프로젝트: newville/xrayweb
def darwinwidth(elem=None):
    edges = atomic = lines = {}
    if elem is not None:
        edges= xraydb.xray_edges(elem)
        atomic= {'n': xraydb.atomic_number(elem),
                 'mass': xraydb.atomic_mass(elem),
                 'density': xraydb.atomic_density(elem)}
        lines= xraydb.xray_lines(elem)
    return render_template('darwinwidth.html', edges=edges, elem=elem,
                           atomic=atomic, lines=lines, materials_dict=materials_dict)
예제 #4
0
def xanesNormalization(e,
                       mu,
                       e0=7125,
                       step=None,
                       nnorm=2,
                       nvict=0,
                       pre1=None,
                       pre2=-50,
                       norm1=100,
                       norm2=None,
                       method="pre_edge",
                       useFlattened=False,
                       Elemline="Fe_K"):

    elem, line = Elemline.split('_')
    elemZ = xraydb.atomic_number(elem)
    dat = Group(name='larchgroup', col1=e, col2=mu)

    if method == "guess":
        result = preedge(e, mu, e0, step=step, nnorm=nnorm, nvict=nvict)

        return result["pre1"], result["pre2"], result["norm1"], result["norm2"]

    elif method == "mback":
        mback(e, mu, group=dat, z=elemZ, edge=line, e0=e0, fit_erfc=False)
        return dat.f2, dat.fpp

    else:
        pre_edge(e,
                 mu,
                 group=dat,
                 e0=e0,
                 step=step,
                 nnorm=nnorm,
                 nvict=nvict,
                 pre1=pre1,
                 pre2=pre2,
                 norm1=norm1,
                 norm2=norm2,
                 make_flat=True)

        if useFlattened:
            normSpec = dat.flat
        else:
            normSpec = dat.norm

        return dat.pre_edge, dat.post_edge, normSpec
예제 #5
0
파일: webapp.py 프로젝트: newville/xrayweb
def element(elem=None):
    edges = atomic = lines = {}
    if elem is not None:
        atomic= {'n': xraydb.atomic_number(elem),
                 'mass': xraydb.atomic_mass(elem),
                 'density': xraydb.atomic_density(elem)}
        _edges= xraydb.xray_edges(elem)
        _lines= xraydb.xray_lines(elem)
        lines = OrderedDict()
        for k in sorted(_lines.keys()):
            lines[k] = _lines[k]

        edges = OrderedDict()
        for k in sorted(_edges.keys()):
            edges[k] = _edges[k]
    return render_template('elements.html', edges=edges, elem=elem,
                           atomic=atomic, lines=lines, materials_dict=materials_dict)
예제 #6
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')
예제 #7
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)
예제 #8
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)
예제 #9
0
    def process(self, dgroup=None, force_mback=False, noskip=False, **kws):
        """ handle process (pre-edge/normalize) of XAS data from XAS form
        """
        if self.skip_process and not noskip:
            return
        if dgroup is None:
            dgroup = self.controller.get_group()
        if dgroup is None:
            return
        self.skip_process = True
        conf = self.get_config(dgroup)
        dgroup.custom_plotopts = {}

        form = self.read_form()
        form['group'] = dgroup.groupname

        if dgroup.datatype != 'xas':
            self.skip_process = False
            dgroup.mu = dgroup.ydat * 1.0
            opts = {'group': dgroup.groupname, 'scale': conf.get('scale', 1.0)}
            self.larch_eval("{group:s}.scale = {scale:.8f}".format(**opts))
            self.larch_eval(
                "{group:s}.norm = {scale:.8f}*{group:s}.ydat".format(**opts))
            return

        en_units = getattr(dgroup, 'energy_units', None)
        if en_units is None:
            en_units = guess_energy_units(dgroup.energy)

        if en_units != 'eV':
            mono_dspace = getattr(dgroup, 'mono_dspace', 1)
            dlg = EnergyUnitsDialog(self.parent,
                                    dgroup.energy,
                                    unitname=en_units,
                                    dspace=mono_dspace)
            res = dlg.GetResponse()
            dlg.Destroy()
            if res.ok:
                en_units = res.units
                dgroup.mono_dspace = res.dspace
                dgroup.xdat = dgroup.energy = res.energy
        dgroup.energy_units = en_units

        e0 = form['e0']
        edge_step = form['edge_step']

        copts = [dgroup.groupname]
        if not form['auto_e0']:
            if e0 < max(dgroup.energy) and e0 > min(dgroup.energy):
                copts.append("e0=%.4f" % float(e0))

        if not form['auto_step']:
            copts.append("step=%s" % gformat(float(edge_step)))

        for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'):
            if form[attr] is None:
                copts.append("%s=None" % attr)
            else:
                copts.append("%s=%.2f" % (attr, form[attr]))

        self.larch_eval("pre_edge(%s)" % (', '.join(copts)))
        self.larch_eval(
            "{group:s}.norm_poly = 1.0*{group:s}.norm".format(**form))

        norm_method = form['norm_method'].lower()
        form['normmeth'] = 'poly'
        if force_mback or norm_method.startswith('mback'):
            form['normmeth'] = 'mback'
            copts = [dgroup.groupname]
            copts.append("z=%d" % atomic_number(form['atsym']))
            copts.append("edge='%s'" % form['edge'])
            for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'):
                if form[attr] is None:
                    copts.append("%s=None" % attr)
                else:
                    copts.append("%s=%.2f" % (attr, form[attr]))

            self.larch_eval("mback_norm(%s)" % (', '.join(copts)))

            if form['auto_step']:
                norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}"""
                self.larch_eval(norm_expr.format(**form))
            else:
                norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
{group:s}.norm *= {group:s}.edge_step_{normmeth:s}/{edge_step:.8f}"""
                self.larch_eval(norm_expr.format(**form))

        if norm_method.startswith('area'):
            form['normmeth'] = 'area'
            expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s}
{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}"""
            self.larch_eval(expr.format(**form))

        self.make_dnormde(dgroup)

        if form['auto_e0']:
            self.wids['e0'].SetValue(dgroup.e0)
        if form['auto_step']:
            self.wids['step'].SetValue(dgroup.edge_step)
            autoset_fs_increment(self.wids['step'], dgroup.edge_step)

        self.wids['atsym'].SetStringSelection(dgroup.atsym)
        self.wids['edge'].SetStringSelection(dgroup.edge)

        self.set_nnorm_widget(dgroup.pre_edge_details.nnorm)
        for attr in ('e0', 'edge_step'):
            conf[attr] = getattr(dgroup, attr)
        for attr in ('pre1', 'pre2', 'norm1', 'norm2'):
            conf[attr] = val = getattr(dgroup.pre_edge_details, attr, None)
            if val is not None:
                self.wids[attr].SetValue(val)

        if hasattr(dgroup, 'mback_params'):  # from mback
            conf['atsym'] = getattr(dgroup.mback_params, 'atsym')
            conf['edge'] = getattr(dgroup.mback_params, 'edge')
        self.update_config(conf, dgroup=dgroup)
        wx.CallAfter(self.unset_skip_process)
예제 #10
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