Exemplo n.º 1
0
    def __init__(self,
                 name,
                 formula,
                 cell_volume=None,
                 density=None,
                 charge=0):
        # Fill in density or cell_volume.
        M = pt.formula(formula, natural_density=density)
        if cell_volume is not None:
            M.density = 1e24 * M.molecular_mass / cell_volume if cell_volume > 0 else 0
            #print name, M.molecular_mass, cell_volume, M.density
        else:
            cell_volume = 1e24 * M.molecular_mass / M.density

        Hnatural = isotope_substitution(M, pt.T, pt.H)
        H = isotope_substitution(M, pt.T, pt.H[1])
        D = isotope_substitution(M, pt.T, pt.D)

        self.name = name
        self.formula = M
        self.cell_volume = cell_volume
        self.sld = pt.neutron_sld(Hnatural, wavelength=5)[0]
        self.Hsld = pt.neutron_sld(H, wavelength=5)[0]
        self.Dsld = pt.neutron_sld(D, wavelength=5)[0]
        self.mass, self.Hmass, self.Dmass = Hnatural.mass, H.mass, D.mass
        self.D2Omatch = D2Omatch(self.sld, self.Dsld)
        self.charge = charge
        self.Hnatural = Hnatural
Exemplo n.º 2
0
    def __init__(self,
                 name,
                 formula,
                 cell_volume=None,
                 natural_density=None,
                 charge=0):
        M = pt.formula(formula, natural_density=natural_density)

        # Fill in density or cell_volume
        if cell_volume is not None:
            M.density = 1e24 * M.molecular_mass / cell_volume if cell_volume > 0 else 0
        else:
            cell_volume = 1e24 * M.molecular_mass / M.density

        self.cell_volume = cell_volume
        self.name = name
        self.formula = M
        self.natural = isotope_substitution(M, pt.T, pt.H)
        self.H = isotope_substitution(M, pt.T, pt.H[1])
        self.D = isotope_substitution(M, pt.T, pt.D)

        self.sld = pt.neutron_sld(self.natural, wavelength=5)[0]
        self.H_sld = pt.neutron_sld(self.H, wavelength=5)[0]
        self.D_sld = pt.neutron_sld(self.D, wavelength=5)[0]

        self.D2Omatch = D2Omatch(self.H_sld, self.D_sld)
        self.charge = charge
Exemplo n.º 3
0
def test():
    # Regression test: make sure neutron sld is an isotope property
    # Note: it is important that this test be run separately
    D2O = periodictable.formula('D2O',density=20./18)
    D2O_coh,D2O_abs,D2O_inc = periodictable.neutron_sld(D2O)
    D2O_coh2,D2O_abs2,D2O_inc2 = periodictable.neutron_sld(D2O)
    H2O = periodictable.formula('H2O',density=1)
    H2O_coh,H2O_abs,H2O_inc = periodictable.neutron_sld(H2O)
    assert D2O_coh == D2O_coh2
    assert D2O_coh != H2O_coh
Exemplo n.º 4
0
def test():
    # Regression test: make sure neutron sld is an isotope property
    # Note: it is important that this test be run separately
    D2O = periodictable.formula('D2O', density=20. / 18)
    D2O_coh, D2O_abs, D2O_inc = periodictable.neutron_sld(D2O)
    D2O_coh2, D2O_abs2, D2O_inc2 = periodictable.neutron_sld(D2O)
    H2O = periodictable.formula('H2O', density=1)
    H2O_coh, H2O_abs, H2O_inc = periodictable.neutron_sld(H2O)
    assert D2O_coh == D2O_coh2
    assert D2O_coh != H2O_coh
Exemplo n.º 5
0
    def calculate(self):
        try:
            formula = pt.formula(self.ui.chemical_formula.text(), )

        except (pyparsing.ParseException, TypeError, ValueError):
            return

        density = self.ui.mass_density.value()
        molecular_volume = self.ui.molecular_volume.value()
        neutron_wavelength = self.ui.neutron_wavelength.value()
        xray_energy = self.ui.xray_energy.value()

        if self.ui.use_volume.isChecked():
            density = formula.molecular_mass / formula.volume(
                a=molecular_volume, b=1, c=1)
            self.ui.mass_density.setValue(density)

        elif self.ui.use_density.isChecked():
            volume = formula.mass / density / \
                pt.constants.avogadro_number * 1e24
            self.ui.molecular_volume.setValue(volume)

        real, imag, mu = pt.neutron_sld(formula,
                                        density=density,
                                        wavelength=neutron_wavelength)

        self.ui.neutron_SLD.setText('%.6g' % real + ' + ' + '%.6g' % imag +
                                    'j')

        real, imag = pt.xray_sld(formula, density=density, energy=xray_energy)

        self.ui.xray_SLD.setText('%.6g' % real + ' + ' + '%.6g' % imag + 'j')
Exemplo n.º 6
0
    def __init__(self, name, formula, cell_volume=None, density=None, charge=0):
        # Fill in density or cell_volume
        M = pt.formula(formula, natural_density=density)
        if cell_volume != None:
            M.density = 1e24*M.molecular_mass/cell_volume if cell_volume>0 else 0
            #print name, M.molecular_mass, cell_volume, M.density
        else:
            cell_volume = 1e24*M.molecular_mass/M.density

        Hnatural = isotope_substitution(M, pt.T, pt.H)
        H = isotope_substitution(M, pt.T, pt.H[1])
        D = isotope_substitution(M, pt.T, pt.D)

        self.name = name
        self.formula = M
        self.cell_volume = cell_volume
        self.sld = pt.neutron_sld(Hnatural, wavelength=5)[0]
        self.Hsld = pt.neutron_sld(H, wavelength=5)[0]
        self.Dsld = pt.neutron_sld(D, wavelength=5)[0]
        self.mass, self.Hmass, self.Dmass = Hnatural.mass, H.mass, D.mass
        self.D2Omatch = D2Omatch(self.Hsld, self.Dsld)
        self.charge = charge
Exemplo n.º 7
0
    def neutron_scattering_lengths(self,
                                   condition,
                                   vf_d_solvent=1,
                                   neutron_wavelength=1.8):
        vh, vt = self.conditions[condition]

        hf = exchange_protons_formula(self.hf, self.head_exchangable,
                                      vf_d_solvent)
        tf = exchange_protons_formula(self.tf, self.tail_exchangable,
                                      vf_d_solvent)

        h_density = calculate_density(hf, vh)
        t_density = calculate_density(tf, vt)

        h_sld = pt.neutron_sld(hf,
                               density=h_density,
                               wavelength=neutron_wavelength)
        t_sld = pt.neutron_sld(tf,
                               density=t_density,
                               wavelength=neutron_wavelength)
        h_scatlen = complex(*h_sld[0:2]) * vh / 1e6
        t_scatlen = complex(*t_sld[0:2]) * vt / 1e6
        return h_scatlen, t_scatlen
Exemplo n.º 8
0
    def calculate(self):
        try:
            formula = pt.formula(self.ui.chemical_formula.text())

        except (pyparsing.ParseException, TypeError, ValueError, KeyError):
            # a problem was experience during parsing of the formula.
            return

        if not len(formula.atoms):
            return

        density = self.ui.mass_density.value()
        molecular_volume = self.ui.molecular_volume.value()
        neutron_wavelength = self.ui.neutron_wavelength.value()
        xray_energy = self.ui.xray_energy.value()

        if self.ui.use_volume.isChecked():
            density = formula.molecular_mass / formula.volume(
                a=molecular_volume, b=1, c=1)
            self.ui.mass_density.setValue(density)

        elif self.ui.use_density.isChecked():
            try:
                volume = (formula.mass / density /
                          pt.constants.avogadro_number * 1e24)
            except ZeroDivisionError:
                volume = np.nan
            self.ui.molecular_volume.setValue(volume)

        try:
            real, imag, mu = pt.neutron_sld(formula,
                                            density=density,
                                            wavelength=neutron_wavelength)

            self.ui.neutron_SLD.setText("%.6g" % real + " + " + "%.6g" % imag +
                                        "j")
        except Exception:
            self.ui.neutron_SLD.setText("NaN")

        try:
            real, imag = pt.xray_sld(formula,
                                     density=density,
                                     energy=xray_energy)

            self.ui.xray_SLD.setText("%.6g" % real + " + " + "%.6g" % imag +
                                     "j")
        except Exception:
            self.ui.xray_SLD.setText("NaN")
Exemplo n.º 9
0
    def calculate(self):
        try:
            formula = pt.formula(self.ui.chemical_formula.text(),)

        except (pyparsing.ParseException, TypeError, ValueError):
            return

        density = self.ui.mass_density.value()
        molecular_volume = self.ui.molecular_volume.value()
        neutron_wavelength = self.ui.neutron_wavelength.value()
        xray_energy = self.ui.xray_energy.value()

        if self.ui.use_volume.isChecked():
            density = formula.molecular_mass / formula.volume(
                a=molecular_volume,
                b=1,
                c=1)
            self.ui.mass_density.setValue(density)

        elif self.ui.use_density.isChecked():
            volume = formula.mass / density / \
                pt.constants.avogadro_number * 1e24
            self.ui.molecular_volume.setValue(volume)

        real, imag, mu = pt.neutron_sld(formula,
                                        density=density,
                                        wavelength=neutron_wavelength)

        self.ui.neutron_SLD.setText(
            '%.6g' %
            real +
            ' + ' +
            '%.6g' %
            imag +
            'j')

        real, imag = pt.xray_sld(formula,
                                 density=density,
                                 energy=xray_energy)

        self.ui.xray_SLD.setText('%.6g' % real + ' + ' + '%.6g' % imag + 'j')
Exemplo n.º 10
0
def test():
    H, He, D, O = elements.H, elements.He, elements.D, elements.O
    assert H.neutron.absorption == 0.3326
    assert H.neutron.total == 82.02
    assert H.neutron.incoherent == 80.26
    assert H.neutron.coherent == 1.7568
    assert elements.Ru[101].neutron.bp == None
    assert H[1].nuclear_spin == '1/2'
    assert H[2].nuclear_spin == '1'
    assert not H[6].neutron.has_sld()

    assert He[3].neutron.b_c_i == -1.48
    assert He[3].neutron.bm_i == -5.925

    Nb = elements.Nb
    assert Nb.neutron.absorption == Nb[93].neutron.absorption

    # Check that b_c values match abundance-weighted values
    # Note: Currently they do not for match within 5% for Ar,V,Sm or Gd
    for el in elements:
        if not hasattr(el, 'neutron'): continue
        b_c = 0
        complete = True
        for iso in el:
            if iso.neutron != None:
                if iso.neutron.b_c == None:
                    complete = False
                else:
                    b_c += iso.neutron.b_c * iso.neutron.abundance / 100.
        if complete and b_c != 0 and abs((b_c - el.neutron.b_c) / b_c) > 0.05:
            err = abs((b_c - el.neutron.b_c) / b_c)
            ## Printing suppressed for the release version
            #print("%2s %.3f % 7.3f % 7.3f"%(el.symbol,err,b_c,el.neutron.b_c))

    # Check neutron_sld and neutron_xs against NIST calculator
    # Note that we are using different tables, so a general comparison with
    # NIST numbers is not possible, but ^30Si and ^18O are the same in both.
    M = formula('Si[30]O[18]2', density=2.2)
    sld, xs, depth = neutron_scattering(M, wavelength=4.75)
    sld2 = neutron_sld(M, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    #_summarize(M)
    #_summarize(formula('O2',density=1.14))
    # Alan's numbers:
    assert abs(sld[0] - 3.27) < 0.01
    assert abs(sld[1] - 0) < 0.01
    #assert abs(xs[2] - 0.00292) < 0.00001   # TODO fix test
    assert abs(xs[1] - 0.00569) < 0.00001
    #assert abs(depth - 4.329) < 0.001       # TODO fix test

    # Cu/Mo K-alpha = 1.89e-5 + 2.45e-7i / 1.87e-5 + 5.16e-8i

    Ni, Si = elements.Ni, elements.Si

    # Make sure molecular calculation corresponds to direct calculation
    sld = neutron_sld('Si', density=Si.density, wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    sld, _, _ = Si.neutron.scattering(wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    sld, xs, depth = neutron_scattering('Si',
                                        density=Si.density,
                                        wavelength=4.75)
    sld2, xs2, depth2 = Si.neutron.scattering(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-10 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # incoherent cross sections for Ni[62] used to be negative
    sld, xs, depth = neutron_scattering('Ni[62]',
                                        density=Ni[62].density,
                                        wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    sld, xs, depth = Ni[62].neutron.scattering(wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    assert Ni[62].neutron.sld()[2] == 0

    # Test call from periodictable
    sld, xs, depth = periodictable.neutron_scattering('H2O',
                                                      density=1,
                                                      wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('H2O', density=1, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-10 for v, w in zip(xs, xs2))
    assert depth == depth2
    sld = periodictable.neutron_sld('H2O', density=1, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    # Check empty formula
    sld, xs, depth = neutron_scattering('', density=0, wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert np.isinf(depth)

    # Check density == 0 works
    sld, xs, depth = neutron_scattering('Si', density=0, wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert np.isinf(depth)

    # Test natural density
    D2O_density = (2 * D.mass + O.mass) / (2 * H.mass + O.mass)
    sld, xs, depth = neutron_scattering('D2O',
                                        natural_density=1,
                                        wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('D2O',
                                           density=D2O_density,
                                           wavelength=4.75)
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # Test that sld depends on density not on the size of the unit cell
    D2O_density = (2 * D.mass + O.mass) / (2 * H.mass + O.mass)
    sld, xs, depth = neutron_scattering('D2O',
                                        natural_density=1,
                                        wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('2D2O',
                                           natural_density=1,
                                           wavelength=4.75)
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # Test energy <=> velocity <=> wavelength
    assert abs(
        nsf.neutron_wavelength_from_velocity(2200) -
        1.7981972618436388) < 1e-14
    assert abs(nsf.neutron_wavelength(25) - 1.8) < 0.1
    assert abs(nsf.neutron_energy(nsf.neutron_wavelength(25)) - 25) < 1e-14

    # Confirm scattering functions accept energy and wavelength
    sld, xs, depth = neutron_scattering('H2O', density=1, wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('H2O',
                                           density=1,
                                           energy=nsf.neutron_energy(4.75))
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14
Exemplo n.º 11
0
    if type is None:
        if filename.endswith('.fna'):
            type = 'dna'
        elif filename.endswith('.ffn'):
            type = 'dna'
        elif filename.endswith('.faa'):
            type = 'aa'
        elif filename.endswith('.frn'):
            type = 'rna'
        else:
            type = 'aa'
    return type


# Water density at 20C; neutron wavelength doesn't matter (use 5 A).
H2O_SLD = pt.neutron_sld(pt.formula("[email protected]"), wavelength=5)[0]
D2O_SLD = pt.neutron_sld(pt.formula("[email protected]"), wavelength=5)[0]


def D2Omatch(Hsld, Dsld):
    """
    Find the D2O% concentration of solvent such that neutron SLD of the
    material matches the neutron SLD of the solvent.

    *Hsld*, *Dsld* are the SLDs for the hydrogenated and deuterated forms
    of the material respectively, where *D* includes all the labile protons
    swapped for deuterons.  Water SLD is calculated at 20 C.

    Note that the resulting percentage is only meaningful between
    0% to 100%.  Beyond 100% you will need an additional constrast agent
    in the 100% D2O solvent to increase the SLD enough to match.
Exemplo n.º 12
0
def test():
    H,He,D,O = elements.H,elements.He,elements.D,elements.O
    assert H.neutron.absorption == 0.3326
    assert H.neutron.total == 82.02
    assert H.neutron.incoherent == 80.26
    assert H.neutron.coherent == 1.7568
    assert elements.Ru[101].neutron.bp == None
    assert H[1].nuclear_spin == '1/2'
    assert H[2].nuclear_spin == '1'
    assert not H[6].neutron.has_sld()

    assert He[3].neutron.b_c_i == -1.48
    assert He[3].neutron.bm_i == -5.925

    Nb = elements.Nb
    assert Nb.neutron.absorption == Nb[93].neutron.absorption

    # Check that b_c values match abundance-weighted values
    # Note: Currently they do not for match within 5% for Ar,V,Sm or Gd
    for el in elements:
        if not hasattr(el,'neutron'): continue
        b_c = 0
        complete = True
        for iso in el:
            if iso.neutron != None:
                if iso.neutron.b_c == None:
                    complete = False
                else:
                    b_c += iso.neutron.b_c*iso.neutron.abundance/100.
        if complete and b_c != 0 and abs((b_c-el.neutron.b_c)/b_c) > 0.05:
            err = abs((b_c-el.neutron.b_c)/b_c)
            ## Printing suppressed for the release version
            #print("%2s %.3f % 7.3f % 7.3f"%(el.symbol,err,b_c,el.neutron.b_c))

    # Check neutron_sld and neutron_xs against NIST calculator
    # Note that we are using different tables, so a general comparison with
    # NIST numbers is not possible, but ^30Si and ^18O are the same in both.
    M = formula('Si[30]O[18]2',density=2.2)
    sld,xs,depth = neutron_scattering(M,wavelength=4.75)
    sld2 = neutron_sld(M,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    #_summarize(M)
    #_summarize(formula('O2',density=1.14))
    # Alan's numbers:
    assert abs(sld[0] - 3.27) < 0.01
    assert abs(sld[1] - 0) < 0.01
    #assert abs(xs[2] - 0.00292) < 0.00001   # TODO fix test
    assert abs(xs[1] - 0.00569) < 0.00001
    #assert abs(depth - 4.329) < 0.001       # TODO fix test

    # Cu/Mo K-alpha = 1.89e-5 + 2.45e-7i / 1.87e-5 + 5.16e-8i

    Ni,Si = elements.Ni, elements.Si

    # Make sure molecular calculation corresponds to direct calculation
    sld = neutron_sld('Si',density=Si.density,wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    sld,_,_ = Si.neutron.scattering(wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    sld,xs,depth = neutron_scattering('Si',density=Si.density,wavelength=4.75)
    sld2,xs2,depth2 = Si.neutron.scattering(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-10 for v,w in zip(xs,xs2))
    assert abs(depth-depth2) < 1e-14

    # incoherent cross sections for Ni[62] used to be negative
    sld,xs,depth = neutron_scattering('Ni[62]',density=Ni[62].density,
                                      wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    sld,xs,depth = Ni[62].neutron.scattering(wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    assert Ni[62].neutron.sld()[2] == 0


    # Test call from periodictable
    sld,xs,depth = periodictable.neutron_scattering('H2O',density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('H2O',density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-10 for v,w in zip(xs,xs2))
    assert depth==depth2
    sld = periodictable.neutron_sld('H2O',density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    # Check empty formula
    sld,xs,depth = neutron_scattering('',density=0,wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert numpy.isinf(depth)

    # Check density == 0 works
    sld,xs,depth = neutron_scattering('Si',density=0,wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert numpy.isinf(depth)

    # Test natural density
    D2O_density = (2*D.mass + O.mass)/(2*H.mass + O.mass)
    sld,xs,depth = neutron_scattering('D2O',natural_density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('D2O',density=D2O_density,wavelength=4.75)
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14

    # Test that sld depends on density not on the size of the unit cell
    D2O_density = (2*D.mass + O.mass)/(2*H.mass + O.mass)
    sld,xs,depth = neutron_scattering('D2O',natural_density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('2D2O',natural_density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14

    # Test energy <=> velocity <=> wavelength
    assert abs(nsf.neutron_wavelength_from_velocity(2200) - 1.7981972618436388) < 1e-14
    assert abs(nsf.neutron_wavelength(25) - 1.8) < 0.1
    assert abs(nsf.neutron_energy(nsf.neutron_wavelength(25)) - 25) < 1e-14

    # Confirm scattering functions accept energy and wavelength
    sld,xs,depth = neutron_scattering('H2O',density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('H2O',density=1,energy=nsf.neutron_energy(4.75))
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14
Exemplo n.º 13
0
def _guess_type_from_filename(filename, type):
    if type is None:
        if filename.endswith('.fna'):
            type = 'dna'
        elif filename.endswith('.ffn'):
            type = 'dna'
        elif filename.endswith('.faa'):
            type = 'aa'
        elif filename.endswith('.frn'):
            type = 'rna'
        else:
            type = 'aa'
    return type

# Water density at 20C; neutron wavelength doesn't matter (use 5 A).
H2O_SLD = pt.neutron_sld(pt.formula("[email protected]"), wavelength=5)[0]
D2O_SLD = pt.neutron_sld(pt.formula("[email protected]"), wavelength=5)[0]
def D2Omatch(Hsld, Dsld):
    """
    Find the D2O% concentration of solvent such that neutron SLD of the
    material matches the neutron SLD of the solvent.

    *Hsld*, *Dsld* are the SLDs for the hydrogenated and deuterated forms
    of the material respectively, where *D* includes all the labile protons
    swapped for deuterons.  Water SLD is calculated at 20 C.

    Note that the resulting percentage is only meaningful between
    0% to 100%.  Beyond 100% you will need an additional constrast agent
    in the 100% D2O solvent to increase the SLD enough to match.
    """
    # SLD(%Dsample + (1-%)Hsample) = SLD(%D2O + (1-%)H2O)