Esempio n. 1
0
def material_mu(name, energy, density=None, kind='total', _larch=None):
    """
    material_mu(name, energy, density=None, kind='total')

    return X-ray attenuation length (in 1/cm) for a material by name or formula

    arguments
    ---------
     name:     chemical formul or name of material from materials list.
     energy:   energy or array of energies in eV
     density:  material density (gr/cm^3).  If None, and material is a
               known material, that density will be used.
     kind:     'photo' or 'total' (default) for whether to
               return photo-absorption or total cross-section.
    returns
    -------
     mu, absorption length in 1/cm

    notes
    -----
      1.  material names are not case sensitive,
          chemical compounds are case sensitive.
      2.  mu_elam() is used for mu calculation.

    example
    -------
      >>> print material_mu('H2O', 10000.0)
      5.32986401658495
    """
    _materials = get_materials(_larch)
    formula = None
    mater = _materials.get(name.lower(), None)
    if mater is not None:
        formula, density = mater
    else:
        for key, val in _materials.items():
            if name.lower() == val[0].lower(): # match formula
                formula, density = val
                break
    # default to using passed in name as a formula
    if formula is None:
        formula = name
    if density is None:
        raise Warning('material_mu(): must give density for unknown materials')

    mass_tot, mu = 0.0, 0.0
    for elem, frac in chemparse(formula).items():
        mass  = frac * atomic_mass(elem, _larch=_larch)
        mu   += mass * mu_elam(elem, energy, kind=kind, _larch=_larch)
        mass_tot += mass
    return density*mu/mass_tot
Esempio n. 2
0
def material_mu(name, energy, density=None, kind='total', _larch=None):
    """
    material_mu(name, energy, density=None, kind='total')

    return X-ray attenuation length (in 1/cm) for a material by name or formula

    arguments
    ---------
     name:     chemical formul or name of material from materials list.
     energy:   energy or array of energies in eV
     density:  material density (gr/cm^3).  If None, and material is a
               known material, that density will be used.
     kind:     'photo' or 'total' (default) for whether to
               return photo-absorption or total cross-section.
    returns
    -------
     mu, absorption length in 1/cm

    notes
    -----
      1.  material names are not case sensitive,
          chemical compounds are case sensitive.
      2.  mu_elam() is used for mu calculation.

    example
    -------
      >>> print(material_mu('H2O', 10000.0))
      5.32986401658495
    """
    _materials = get_materials(_larch)
    formula = None
    mater = _materials.get(name.lower(), None)
    if mater is not None:
        formula, density = mater
    else:
        for key, val in _materials.items():
            if name.lower() == val[0].lower():  # match formula
                formula, density = val
                break
    # default to using passed in name as a formula
    if formula is None:
        formula = name
    if density is None:
        raise Warning('material_mu(): must give density for unknown materials')

    mass_tot, mu = 0.0, 0.0
    for elem, frac in chemparse(formula).items():
        mass = frac * atomic_mass(elem, _larch=_larch)
        mu += mass * mu_elam(elem, energy, kind=kind, _larch=_larch)
        mass_tot += mass
    return density * mu / mass_tot
Esempio n. 3
0
    def __init__(self, symbol, xray_energy=None, energy_min=1500):
        self.symbol = symbol
        self.xray_energy = xray_energy
        self.mu = 1.0
        self.edges = ['K']
        self.fyields = {}

        if xray_energy is not None:
            self.mu = mu_elam(symbol, xray_energy, kind='photo')

            self.edges = []
            for ename, xedge in xray_edges(self.symbol).items():
                if ename.lower() in ('k', 'l1', 'l2', 'l3', 'm5'):
                    edge_ev = xedge.edge
                    if (edge_ev < xray_energy and
                        edge_ev > energy_min):
                        self.edges.append(ename)
                        self.fyields[ename] = xedge.fyield

        # currently, we consider only one edge per element
        if 'K' in self.edges:
            self.edges = ['K']
        if 'L3' in self.edges:
            tmp = []
            for ename in self.edges:
                if ename.lower().startswith('l'):
                    tmp.append(ename)
            self.edges = tmp

        # apply CK corrections to fluorescent yields
        if 'L3' in self.edges:
            ck13 = ck_probability(symbol, 'L1', 'L3')
            ck12 = ck_probability(symbol, 'L1', 'L2')
            ck23 = ck_probability(symbol, 'L2', 'L3')
            fy3  = self.fyields['L3']
            fy2  = self.fyields.get('L2', 0)
            fy1  = self.fyields.get('L1', 0)
            if 'L2' in self.edges:
                fy3 = fy3 + fy2*ck23
                fy2 = fy2 * (1 - ck23)
                if 'L1' in self.edges:
                    fy3 = fy3 + fy1 * (ck13 + ck12*ck23)
                    fy2 = fy2 + fy1 * ck12
                    fy1 = fy1 * (1 - ck12 - ck13)
                    self.fyields['L1'] = fy1
                self.fyields['L2'] = fy2
            self.fyields['L3'] = fy3
        # look up xray lines
        self.lines = {}
        for ename in self.edges:
            self.lines.update(xray_lines(symbol, ename))
Esempio n. 4
0
def material_mu_components(name,
                           energy,
                           density=None,
                           kind='total',
                           _larch=None):
    """material_mu_components: absorption coefficient (in 1/cm) for a compound

    arguments
    ---------
     name:     material name or compound formula
     energy:   energy or array of energies at which to calculate mu
     density:  compound density in gr/cm^3
     kind:     cross-section to use ('total', 'photo') for mu_elam())

    returns
    -------
     dictionary of data for constructing mu per element,
     with elements 'mass' (total mass), 'density', and
     'elements' (list of atomic symbols for elements in material).
     For each element, there will be an item (atomic symbol as key)
     with tuple of (stoichiometric fraction, atomic mass, mu)

     larch> material_mu_components('quartz', 10000)
     {'Si': (1, 28.0855, 33.879432430185062), 'elements': ['Si', 'O'],
     'mass': 60.0843, 'O': (2.0, 15.9994, 5.9528248152970837), 'density': 2.65}
     """
    _materials = get_materials(_larch)
    mater = _materials.get(name.lower(), None)
    if mater is None:
        formula = name
        if density is None:
            raise Warning(
                'material_mu(): must give density for unknown materials')
    else:
        formula, density = mater

    out = {'mass': 0.0, 'density': density, 'elements': []}
    for atom, frac in chemparse(formula).items():
        mass = atomic_mass(atom, _larch=_larch)
        mu = mu_elam(atom, energy, kind=kind, _larch=_larch)
        out['mass'] += frac * mass
        out[atom] = (frac, mass, mu)
        out['elements'].append(atom)
    return out
Esempio n. 5
0
def material_mu_components(name, energy, density=None, kind='total',
                           _larch=None):
    """material_mu_components: absorption coefficient (in 1/cm) for a compound

    arguments
    ---------
     name:     material name or compound formula
     energy:   energy or array of energies at which to calculate mu
     density:  compound density in gr/cm^3
     kind:     cross-section to use ('total', 'photo') for mu_elam())

    returns
    -------
     dictionary of data for constructing mu per element,
     with elements 'mass' (total mass), 'density', and
     'elements' (list of atomic symbols for elements in material).
     For each element, there will be an item (atomic symbol as key)
     with tuple of (stoichiometric fraction, atomic mass, mu)

     larch> material_mu_components('quartz', 10000)
     {'Si': (1, 28.0855, 33.879432430185062), 'elements': ['Si', 'O'],
     'mass': 60.0843, 'O': (2.0, 15.9994, 5.9528248152970837), 'density': 2.65}
     """
    _materials = get_materials(_larch)
    mater = _materials.get(name.lower(), None)
    if mater is None:
        formula = name
        if density is None:
            raise Warning('material_mu(): must give density for unknown materials')
    else:
        formula, density = mater


    out = {'mass': 0.0, 'density': density, 'elements':[]}
    for atom, frac in chemparse(formula).items():
        mass  = atomic_mass(atom, _larch=_larch)
        mu    = mu_elam(atom, energy, kind=kind, _larch=_larch)
        out['mass'] += frac*mass
        out[atom] = (frac, mass, mu)
        out['elements'].append(atom)
    return out
Esempio n. 6
0
def concentration_resid(pars,
                        lineData=None,
                        mca=None,
                        phiPrime=np.pi / 2.,
                        phiDblPrime=np.pi / 2.,
                        xray_energy=30000.,
                        larch=None):

    cscPhiPrime = 1. / np.sin(phiPrime)
    cscPhiDblPrime = 1. / np.sin(phiDblPrime)
    energy = mca.get_energy() * 1000.
    dE = energy[1] - energy[0]
    probeSpectrum = np.zeros(len(energy))
    ind = index_of(energy, xray_energy)
    probeSpectrum[ind] = 1.0
    C = np.array([pars[elem + '_con'].value for elem in lineData], ndmin=2).T
    Cal = np.array([pars[elem + '_cal'].value for elem in lineData])
    Intensity = np.array([lineData[elem][2] for elem in lineData])

    mu = np.zeros((len(lineData) + 1, len(energy)))
    for i, elem_i in enumerate(lineData):
        mu[i, :] = mu_elam(elem_i, energy, kind='total', _larch=larch)
        mu[-1, :] += C[i, 0] * mu[i, :]

    beta = np.zeros((len(lineData), len(lineData), len(energy)))
    delta = np.zeros((len(lineData), len(lineData), len(energy)))
    for i, elem_i in enumerate(lineData):

        line_en_i = lineData[elem_i][1]

        edge_i = lineData[elem_i][0][len(elem_i)].title()
        edge_en_i, _, r_i = xray_edge(elem_i, edge_i, _larch=larch)

        for j, elem_j in enumerate(lineData):

            line_en_j = lineData[elem_j][1]

            edge_j = lineData[elem_j][0][len(elem_j)].title()
            line_j = lineData[elem_j][0][len(elem_j):].title()
            edge_en_j, _, r_j = xray_edge(elem_j, edge_j, _larch=larch)
            yield_j, _, prob_j = fluo_yield(elem_j,
                                            edge_j,
                                            line_j,
                                            np.max(energy),
                                            _larch=larch)
            k_j = prob_j * yield_j * (r_j - 1.) / r_j

            mu_s_prime = mu[-1, :] * cscPhiPrime
            mu_s_line_en_j = np.interp(line_en_j, energy, mu[-1, :])
            mu_s_dblPrime_line_en_i = np.interp(line_en_i, energy,
                                                mu[-1, :]) * cscPhiDblPrime

            P_ij = np.log(1. + mu_s_prime / mu_s_line_en_j) / mu_s_prime + \
                   np.log(1. + mu_s_dblPrime_line_en_i / mu_s_line_en_j) / mu_s_dblPrime_line_en_i

            beta[i,j,:]  = mu[j,:] * cscPhiPrime + \
                           np.interp(line_en_i, energy, mu[j,:]) * cscPhiDblPrime
            beta[i,j,:] /= mu[i,:] * cscPhiPrime + \
                           np.interp(line_en_i, energy, mu[i,:]) * cscPhiDblPrime
            beta[i, j, :] -= 1.

            delta[i, j, :] = np.where(energy >= edge_en_j, 0.5, 0.0)
            if line_en_j <= edge_en_i: delta[i, j, :] *= 0.
            delta[i, j, :] *= k_j
            delta[i, j, :] *= mu[j, :] * cscPhiPrime
            delta[i, j, :] *= np.interp(line_en_j, energy, mu[i, :])
            delta[i,j,:] /= (mu[-1,:] * cscPhiPrime) + \
                            (np.interp(line_en_i, energy, mu[-1,:]) * cscPhiDblPrime)
            delta[i, j, :] *= P_ij

    W = np.zeros((1, len(lineData), len(energy)))
    for i, elem in enumerate(lineData):
        line_en_i = lineData[elem_i][1]
        mu_i_star = mu[i,:] * cscPhiPrime +\
                    np.interp(line_en_i, energy, mu[i,:]) * cscPhiDblPrime
        W[0, i, :] = mu[i, :] * probeSpectrum * dE
        W[0, i, :] /= mu_i_star * (1 + np.sum(C * beta[i, :, :], axis=0))

    alpha = np.sum(W * beta, axis=2) / np.sum(W, axis=2)
    epsilon = np.sum(W * delta, axis=2) / np.sum(W, axis=2)

    num = 1 + np.sum(C.T * epsilon, axis=1)
    den = 1 + np.sum(C.T * alpha, axis=1)

    C = np.reshape(C, (len(C)))
    print(pars['cu_con'].value, pars['zn_con'].value, pars['mn_con'].value)

    return Intensity - Cal * C * num / den