def test_formula():
    M = formula('B4C', density=2.52)
    sld, xs, depth = neutron_scattering(M, wavelength=4.75)
    # Compare to Alan Munter's numbers:
    #   SLD=7.65e-6 - 2.34e-7i /A^2
    #   inc,abs XS = 0.193, 222.4 / cm
    #   1/e = 0.004483 cm
    #   Cu/Mo K-alpha = 2.02e-5 + 1.93e-8i / 2.01e-5 + 4.64e-9i
    # Using lambda=1.798 rather than 1.8
    #   abs XS => 222.6
    #   1/e => 0.004478
    assert abs(sld[0] - 7.649) < 0.001
    assert abs(sld[1] - 0.234) < 0.001
    assert abs(xs[1] - 222.6) < 0.1
    #assert abs(xs[2]-0.193)<0.001   # TODO: fix test
    #assert abs(depth-0.004478)<0.000001 # TODO: fix test
    # Check that sld_inc and coh_xs are consistent
    #   cell_volume = (molar_mass/density) / N_A * 1e24
    #   number_density = num_atoms/cell_volume
    #   sigma_i = inc_xs/number_density
    #   sld_inc = number_density * sqrt ( 100/(4*pi) * sigma_i ) * 10
    #   sld_re = number_density * b_c * 10
    #   sigma_c = 4*pi/100*b_c**2
    #   coh_xs = sigma_c * number_density
    Nb = 0.13732585020640778
    sld_inc = Nb * sqrt(100 / (4 * pi) * xs[2] / Nb) * 10
    coh_xs = Nb * 4 * pi / 100 * (sld[0] / (10 * Nb))**2
    assert abs(sld[2] - sld_inc) < 1e-14
    assert abs(xs[0] - coh_xs) < 1e-14
def test_formula():
    M = formula('B4C', density=2.52)
    sld,xs,depth = neutron_scattering(M,wavelength=4.75)
    # Compare to Alan Munter's numbers:
    #   SLD=7.65e-6 - 2.34e-7i /A^2
    #   inc,abs XS = 0.193, 222.4 / cm
    #   1/e = 0.004483 cm
    #   Cu/Mo K-alpha = 2.02e-5 + 1.93e-8i / 2.01e-5 + 4.64e-9i
    # Using lambda=1.798 rather than 1.8
    #   abs XS => 222.6
    #   1/e => 0.004478
    assert abs(sld[0]-7.649)<0.001
    assert abs(sld[1]-0.234)<0.001
    assert abs(xs[1]-222.6)<0.1
    #assert abs(xs[2]-0.193)<0.001   # TODO: fix test
    #assert abs(depth-0.004478)<0.000001 # TODO: fix test
    # Check that sld_inc and coh_xs are consistent
    #   cell_volume = (molar_mass/density) / N_A * 1e24
    #   number_density = num_atoms/cell_volume
    #   sigma_i = inc_xs/number_density
    #   sld_inc = number_density * sqrt ( 100/(4*pi) * sigma_i ) * 10
    #   sld_re = number_density * b_c * 10
    #   sigma_c = 4*pi/100*b_c**2
    #   coh_xs = sigma_c * number_density
    Nb = 0.13732585020640778
    sld_inc = Nb*sqrt(100/(4*pi)*xs[2]/Nb)*10
    coh_xs = Nb*4*pi/100*(sld[0]/(10*Nb))**2
    assert abs(sld[2] - sld_inc) < 1e-14
    assert abs(xs[0] - coh_xs) < 1e-14
Exemple #3
0
 def test_neutron_sld(self):
     """
     test sld 
     """
     #Compute incoherence , absorption, and incoherence
     (sld_real,sld_im,sld_inc), (coh,abs,incoh), length = neutron_scattering(self.compound,
                             density=self.density, wavelength=self.wavelength) 
     cu_real, cu_im = calculate_xray_sld(element="Cu", density=self.density,
                               molecule_formula=self.sld_formula)
     mo_real, mo_im = calculate_xray_sld(element="Mo", density=self.density,
                               molecule_formula=self.sld_formula)
     #test sld 
     self.assertAlmostEquals(sld_real * _SCALE, 1.04e-6, 1)
     self.assertAlmostEquals(sld_im * _SCALE, -1.5e-7, 1)
     #test absorption value
     self.assertAlmostEquals(abs, 180.0,0)
     self.assertAlmostEquals(incoh, 0.0754, 2)
     #Test length
     self.assertAlmostEquals(length, 0.005551, 4)
     #test Cu sld
     self.assertAlmostEquals(cu_real * _SCALE, 2.89e-5, 1)
     self.assertAlmostEquals(cu_im * _SCALE, 2.81e-6)
     # test Mo sld
     self.assertAlmostEquals(mo_real * _SCALE, 2.84e-5, 1)
     self.assertAlmostEquals(mo_im * _SCALE, 7.26e-7,1)
Exemple #4
0
 def test_neutron_sld(self):
     """
     test sld 
     """
     #Compute incoherence , absorption, and incoherence
     (sld_real,sld_im,sld_inc), (coh,abs,incoh), length = neutron_scattering(self.compound,
                                    density=self.density, wavelength=self.wavelength) 
     cu_real, cu_im = calculate_xray_sld(element="Cu", density=self.density,
                               molecule_formula=self.sld_formula)
     mo_real, mo_im = calculate_xray_sld(element="Mo", density=self.density,
                               molecule_formula=self.sld_formula)
     #test sld 
     self.assertAlmostEquals(sld_real * _SCALE, 6.33e-6, 1)
     self.assertAlmostEquals(sld_im * _SCALE, 0)
     #test absorption value
     self.assertAlmostEquals(abs, 1.35e-4, 2)
     self.assertAlmostEquals(incoh, 0.138, 2)
     #Test length
     self.assertAlmostEquals(length, 1.549, 3)
     #test Cu sld
     self.assertAlmostEquals(cu_real * _SCALE, 9.36e-6, 1)
     self.assertAlmostEquals(cu_im * _SCALE, 2.98e-8)
     # test Mo sld
     self.assertAlmostEquals(mo_real * _SCALE, 9.33e-6)
     self.assertAlmostEquals(mo_im * _SCALE, 5.59e-9,1)
Exemple #5
0
 def test_neutron_sld(self):
     """
     test sld
     """
     #Compute incoherence , absorption, and incoherence
     (sld_real, sld_im, sld_inc), (coh, abs,
                                   incoh), length = neutron_scattering(
                                       self.compound,
                                       density=self.density,
                                       wavelength=self.wavelength)
     cu_real, cu_im = calculate_xray_sld(element="Cu",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     mo_real, mo_im = calculate_xray_sld(element="Mo",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     #test sld
     self.assertAlmostEquals(sld_real * _SCALE, 1.04e-6, 1)
     self.assertAlmostEquals(sld_im * _SCALE, -1.5e-7, 1)
     #test absorption value
     self.assertAlmostEquals(abs, 180.0, 0)
     self.assertAlmostEquals(incoh, 0.0754, 2)
     #Test length
     self.assertAlmostEquals(length, 0.005551, 4)
     #test Cu sld
     self.assertAlmostEquals(cu_real * _SCALE, 2.89e-5, 1)
     self.assertAlmostEquals(cu_im * _SCALE, 2.81e-6)
     # test Mo sld
     self.assertAlmostEquals(mo_real * _SCALE, 2.84e-5, 1)
     self.assertAlmostEquals(mo_im * _SCALE, 7.26e-7, 1)
Exemple #6
0
 def test_neutron_sld(self):
     """
     test sld
     """
     #Compute incoherence , absorption, and incoherence
     (sld_real, sld_im, sld_inc), (coh, abs,
                                   incoh), length = neutron_scattering(
                                       self.compound,
                                       density=self.density,
                                       wavelength=self.wavelength)
     cu_real, cu_im = calculate_xray_sld(element="Cu",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     mo_real, mo_im = calculate_xray_sld(element="Mo",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     #test sld
     self.assertAlmostEquals(sld_real * _SCALE, 6.33e-6, 1)
     self.assertAlmostEquals(sld_im * _SCALE, 0)
     #test absorption value
     self.assertAlmostEquals(abs, 1.35e-4, 2)
     self.assertAlmostEquals(incoh, 0.138, 2)
     #Test length
     self.assertAlmostEquals(length, 1.549, 3)
     #test Cu sld
     self.assertAlmostEquals(cu_real * _SCALE, 9.36e-6, 1)
     self.assertAlmostEquals(cu_im * _SCALE, 2.98e-8)
     # test Mo sld
     self.assertAlmostEquals(mo_real * _SCALE, 9.33e-6)
     self.assertAlmostEquals(mo_im * _SCALE, 5.59e-9, 1)
Exemple #7
0
    def calculate(self):
        compound = self.get_compound()
        wavelength_n = self.get_neutron_wavelength()
        wavelength_x = self.get_xray_wavelength()
        thickness = self.get_thickness()

        if compound is None or compound.density is None or wavelength_x is None or wavelength_n is None or thickness is None:
            return

        res = neutron_scattering(compound,
                                 density=compound.density,
                                 wavelength=wavelength_n)

        if res == (None, None, None):
            hightlight(self.ui.lE_SLD_sample_material)
            self._log_ex("missing neutron cross sections")
            return

        try:
            self.calculate_penetration_depth(compound, wavelength_n,
                                             wavelength_x, thickness)
            self.calculate_sld(compound, wavelength_n, wavelength_x)
            self.calculate_cross_sections(compound, wavelength_n, wavelength_x)
            self.calculate_critical_reflection(wavelength_n, wavelength_x)
        except Exception as e:
            self._log_ex(e)
Exemple #8
0
 def test_neutron_sld(self):
     """
     test sld
     """
     #Compute incoherence , absorption, and incoherence
     (sld_real, sld_im, sld_inc), (coh, abs,
                                   incoh), length = neutron_scattering(
                                       self.compound,
                                       density=self.density,
                                       wavelength=self.wavelength)
     cu_real, cu_im = calculate_xray_sld(element="Cu",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     mo_real, mo_im = calculate_xray_sld(element="Mo",
                                         density=self.density,
                                         molecule_formula=self.sld_formula)
     #test sld
     self.assertAlmostEqual(sld_real * _SCALE, -5.6e-7, 1)
     self.assertAlmostEqual(sld_im * _SCALE, 0)
     #test absorption value
     self.assertAlmostEqual(abs, 0.0741, 2)
     self.assertAlmostEqual(incoh, 5.62, 2)
     #Test length
     self.assertAlmostEqual(length, 0.1755, 3)
     #test Cu sld
     self.assertAlmostEqual(cu_real * _SCALE, 9.46e-6, 1)
     self.assertAlmostEqual(cu_im * _SCALE, 3.01e-8)
     # test Mo sld
     self.assertAlmostEqual(mo_real * _SCALE, 9.43e-6)
     self.assertAlmostEqual(mo_im * _SCALE, 5.65e-7, 1)
Exemple #9
0
 def calculateSld(self, event):
     """
         Calculate the neutron scattering density length of a molecule
     """
     self.clear_outputs()
     try:
         #Check validity user inputs
         flag, msg = self.check_inputs()
         if self.base is not None and msg.lstrip().rstrip() != "":
             msg = "SLD Calculator: %s" % str(msg)
             wx.PostEvent(self.base, StatusEvent(status=msg))
         if not flag:
             return
         #get ready to compute
         self.sld_formula = formula(self.compound, density=self.density)
         (sld_real, sld_im, _), (_, absorp, incoh), \
                     length = neutron_scattering(compound=self.compound,
                                density=self.density,
                                wavelength=self.neutron_wavelength)
         if self.xray_source == "[A]":
             energy = xray_energy(self.xray_source_input)
             xray_real, xray_im = xray_sld_from_atoms(
                 self.sld_formula.atoms,
                 density=self.density,
                 energy=energy)
         elif self.xray_source == "[keV]":
             xray_real, xray_im = xray_sld_from_atoms(
                 self.sld_formula.atoms,
                 density=self.density,
                 energy=self.xray_source_input)
         elif self.xray_source == "Element":
             xray_real, xray_im = self.calculate_sld_helper(
                 element=self.xray_source_input,
                 density=self.density,
                 molecule_formula=self.sld_formula)
         # set neutron sld values
         val = format_number(sld_real * _SCALE)
         self.neutron_sld_real_ctl.SetValue(val)
         val = format_number(math.fabs(sld_im) * _SCALE)
         self.neutron_sld_im_ctl.SetValue(val)
         # Compute the Cu SLD
         self.xray_sld_real_ctl.SetValue(format_number(xray_real * _SCALE))
         val = format_number(math.fabs(xray_im) * _SCALE)
         self.xray_sld_im_ctl.SetValue(val)
         # set incoherence and absorption
         self.neutron_inc_ctl.SetValue(format_number(incoh))
         self.neutron_abs_ctl.SetValue(format_number(absorp))
         # Neutron length
         self.neutron_length_ctl.SetValue(format_number(length))
         # display wavelength
         #self.wavelength_ctl.SetValue(str(self.wavelength))
         #self.wavelength_ctl.SetValue(str(self.wavelength))
     except:
         if self.base is not None:
             msg = "SLD Calculator: %s" % (sys.exc_value)
             wx.PostEvent(self.base, StatusEvent(status=msg))
     if event is not None:
         event.Skip()
Exemple #10
0
 def calculateSld(self, event):
     """
         Calculate the neutron scattering density length of a molecule
     """
     self.clear_outputs()
     try:
         #Check validity user inputs
         flag, msg = self.check_inputs()
         if self.base is not None and msg.lstrip().rstrip() != "":
             msg = "SLD Calculator: %s" % str(msg)
             wx.PostEvent(self.base, StatusEvent(status=msg))
         if not flag:
            return
         #get ready to compute
         self.sld_formula = formula(self.compound,
                                         density=self.density)
         (sld_real, sld_im, _), (_, absorp, incoh), \
                     length = neutron_scattering(compound=self.compound,
                                density=self.density,
                                wavelength=self.neutron_wavelength)
         if self.xray_source == "[A]":
             energy = xray_energy(self.xray_source_input)
             xray_real, xray_im = xray_sld_from_atoms(self.sld_formula.atoms,
                                                      density=self.density,
                                                      energy=energy)
         elif self.xray_source == "[keV]":
             xray_real, xray_im = xray_sld_from_atoms(self.sld_formula.atoms,
                                                      density=self.density,
                                                      energy=self.xray_source_input)
         elif self.xray_source == "Element":
             xray_real, xray_im = self.calculate_sld_helper(element=self.xray_source_input,
                                                            density=self.density,
                                                            molecule_formula=self.sld_formula)
         # set neutron sld values
         val = format_number(sld_real * _SCALE)
         self.neutron_sld_real_ctl.SetValue(val)
         val = format_number(math.fabs(sld_im) * _SCALE)
         self.neutron_sld_im_ctl.SetValue(val)
         # Compute the Cu SLD
         self.xray_sld_real_ctl.SetValue(format_number(xray_real * _SCALE))
         val = format_number(math.fabs(xray_im) * _SCALE)
         self.xray_sld_im_ctl.SetValue(val)
         # set incoherence and absorption
         self.neutron_inc_ctl.SetValue(format_number(incoh))
         self.neutron_abs_ctl.SetValue(format_number(absorp))
         # Neutron length
         self.neutron_length_ctl.SetValue(format_number(length))
         # display wavelength
         #self.wavelength_ctl.SetValue(str(self.wavelength))
         #self.wavelength_ctl.SetValue(str(self.wavelength))
     except:
         if self.base is not None:
             msg = "SLD Calculator: %s" % (sys.exc_value)
             wx.PostEvent(self.base, StatusEvent(status=msg))
     if event is not None:
         event.Skip()
Exemple #11
0
    def calculate_penetration_depth(self, compound, wavelength_n, wavelength_x,
                                    thickness):
        _, xs, _ = neutron_scattering(compound,
                                      density=compound.density,
                                      wavelength=wavelength_n)
        sld_x_real, sld_x_imag = xray_sld(compound,
                                          density=compound.density,
                                          wavelength=wavelength_x)

        xs_coh, xs_abs, xs_incoh = xs
        p_abs, p_abs_incoh, p_abs_incoh_coh = [
            1 / xs_abs, 1 / (xs_abs + xs_incoh),
            1 / (xs_abs + xs_coh + xs_incoh)
        ]
        p_abs_r, p_abs_incoh_r, p_abs_incoh_coh_r = self._r(
            [p_abs, p_abs_incoh, p_abs_incoh_coh])

        # not 100% sure about the 1/2...
        p_abs_xray = 1 / (2 * wavelength_x * sld_x_imag * 1e-6) * 1e-4

        tr_att = lambda d, pen: (np.exp(-d / pen) * 100, np.exp(d / pen))
        # thickness is in [m], p_abs_incoh in [cm], thus 1e-2
        tr_n, att_n = tr_att(thickness, p_abs_incoh * 1e-2)
        # p_abs_xray in [µm], thus 1e-6
        tr_x, att_x = tr_att(thickness, p_abs_xray * 1e-6)

        self.ui.lE_SLD_pendepth_neutron_abs.setText(f"{p_abs_r}")
        self.ui.lE_SLD_pendepth_neutron_abs_incoh.setText(f"{p_abs_incoh_r}")
        self.ui.lE_SLD_pendepth_neutron_abs_incoh_coh.setText(
            f"{p_abs_incoh_coh_r}")
        self.ui.lE_SLD_pendepth_neutron_transmission.setText(f"{tr_n} %")
        self.ui.lE_SLD_pendepth_neutron_attenuation.setText(f"{att_n}")

        self.ui.lE_SLD_pendepth_xray_abs.setText(f"{self._r(p_abs_xray)}")
        self.ui.lE_SLD_pendepth_xray_transmission.setText(f"{tr_x} %")
        self.ui.lE_SLD_pendepth_xray_attenuation.setText(f"{att_x}")
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
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