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
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 cgi_call(): form = cgi.FieldStorage() #print >>sys.stderr, form #print >>sys.stderr, "sample",form.getfirst('sample') #print >>sys.stderr, "mass",form.getfirst('mass') # Parse inputs errors = {}; calculate = form.getfirst('calculate','all') if calculate not in ('scattering','activation','all'): errors['calculate'] = "calculate should be one of 'scattering', 'activation' or 'all'" try: chem = formula(form.getfirst('sample')) except: errors['sample'] = error() try: fluence = float(form.getfirst('flux',100000)) except: errors['flux'] = error() try: fast_ratio = float(form.getfirst('fast','0')) except: errors['fast'] = error() try: Cd_ratio = float(form.getfirst('Cd','0')) except: errors['Cd'] = error() try: exposure = parse_hours(form.getfirst('exposure','1')) except: errors['exposure'] = error() try: mass_str = form.getfirst('mass','1') if mass_str.endswith('kg'): mass = 1000*float(mass_str[:-2]) elif mass_str.endswith('mg'): mass = 0.001*float(mass_str[:-2]) elif mass_str.endswith('ug'): mass = 1e-6*float(mass_str[:-2]) elif mass_str.endswith('g'): mass = float(mass_str[:-1]) else: mass = float(mass_str) except: errors['mass'] = error() try: density_type,density_value = parse_density(form.getfirst('density','0')) except: errors['density'] = error() try: #print >>sys.stderr,form.getlist('rest[]') rest_times = [parse_rest(v) for v in form.getlist('rest[]')] if not rest_times: rest_times = [0,1,24,360] except: errors['rest'] = error() try: decay_level = float(form.getfirst('decay','0.001')) except: errors['decay'] = error() try: thickness = float(form.getfirst('thickness', '1')) except: errors['thickness'] = error() try: wavelength_str = form.getfirst('wavelength','1').strip() if wavelength_str.endswith('meV'): wavelength = nsf.neutron_wavelength(float(wavelength_str[:-3])) elif wavelength_str.endswith('m/s'): wavelength = nsf.neutron_wavelength_from_velocity(float(wavelength_str[:-3])) elif wavelength_str.endswith('Ang'): wavelength = float(wavelength_str[:-3]) else: wavelength = float(wavelength_str) #print >>sys.stderr,wavelength_str except: errors['wavelength'] = error() try: xray_source = form.getfirst('xray','Cu Ka').strip() if xray_source.endswith('Ka'): xray_wavelength = elements.symbol(xray_source[:-2].strip()).K_alpha elif xray_source.endswith('keV'): xray_wavelength = xsf.xray_wavelength(float(xray_source[:-3])) elif xray_source.endswith('Ang'): xray_wavelength = float(xray_source[:-3]) elif xray_source[0].isalpha(): xray_wavelength = elements.symbol(xray_source).K_alpha else: xray_wavelength = float(xray_source) #print >>sys.stderr,"xray",xray_source,xray_wavelength except: errors['xray'] = error() try: abundance_source = form.getfirst('abundance','IAEA') if abundance_source == "NIST": abundance = activation.NIST2001_isotopic_abundance elif abundance_source == "IAEA": abundance = activation.IAEA1987_isotopic_abundance else: raise ValueError("abundance should be NIST or IAEA") except: errors['abundance'] = error() if errors: return {'success':False, 'error':'invalid request', 'detail':errors} # Fill in defaults #print >>sys.stderr,density_type,density_value,chem.density if density_type == 'default' or density_value == 0: # default to a density of 1 if chem.density is None: chem.density = 1 elif density_type == 'volume': chem.density = chem.molecular_mass/density_value elif density_type == 'natural': # if density is given, assume it is for natural abundance chem.natural_density = density_value elif density_type == 'isotope': chem.density = density_value else: raise ValueError("unknown density type %r"%density_type) result = {'success': True} result['sample'] = { 'formula': str(chem), 'mass': mass, 'density': chem.density, 'thickness': thickness, 'natural_density': chem.natural_density, } # Run calculations if calculate in ('activation', 'all'): try: env = activation.ActivationEnvironment(fluence=fluence,fast_ratio=fast_ratio, Cd_ratio=Cd_ratio) sample = activation.Sample(chem, mass=mass) sample.calculate_activation(env,exposure=exposure,rest_times=rest_times,abundance=abundance) decay_time = sample.decay_time(decay_level) total = [0]*len(sample.rest_times) rows = [] for el,activity_el in activation.sorted_activity(sample.activity.items()): total = [t+a for t,a in zip(total,activity_el)] rows.append({'isotope':el.isotope,'reaction':el.reaction,'product':el.daughter, 'halflife':el.Thalf_str,'comments':el.comments,'levels':activity_el}) result['activation'] = { 'flux': fluence, 'fast': fast_ratio, 'Cd': Cd_ratio, 'exposure': exposure, 'rest': rest_times, 'activity': rows, 'total': total, 'decay_level': decay_level, 'decay_time': decay_time, } #print >>sys.stderr,result except: result['activation'] = {"error": error()} #nsf_sears.replace_neutron_data() if calculate in ('scattering', 'all'): try: sld,xs,penetration = neutron_scattering(chem, wavelength=wavelength) result['scattering'] = { 'neutron': { 'wavelength': wavelength, 'energy': nsf.neutron_energy(wavelength), 'velocity': nsf.VELOCITY_FACTOR/wavelength, }, 'xs': {'coh': xs[0], 'abs': xs[1], 'incoh': xs[2]}, 'sld': {'real': sld[0], 'imag': sld[1], 'incoh': sld[2]}, 'penetration': penetration, 'transmission': 100*exp(-thickness/penetration), } except: missing = [str(el) for el in chem.atoms if not el.neutron.has_sld()] if any(missing): msg = "missing neutron cross sections for "+", ".join(missing) else: msg = error() result['scattering'] = {'error': msg } try: xsld = xray_sld(chem, wavelength=xray_wavelength) result['xray_scattering'] = { 'xray': { 'wavelength': xray_wavelength, 'energy': xsf.xray_energy(xray_wavelength), }, 'sld': {'real': xsld[0], 'imag': xsld[1]}, } except: result['xray_scattering'] = {'error': error()} return result