def from_string(text, xray_database: TransitionDatabase): """ Returns a wavelength parsed from a text in units of Angstrom :param text: :param xray_database: :return: """ if any([emisson_line in text for emisson_line in EMISSON_LINES.keys()]): for emisson_line in EMISSON_LINES.keys(): if not emisson_line in text: continue element = text.replace(emisson_line, '').strip() transitions = xray_database.get_all_transitions( element, EMISSON_LINES[emisson_line]) if len(transitions) != 1: raise WavelengthError( f"Unknown transition line for '{text}'") # transition db returns in eV, xray-wavelength expects keV return xray_wavelength( transitions[EMISSON_LINES[emisson_line]]['experimental'] * 1e-3) try: if 'AA' in text or 'Ang' in text: wavelength = float(text.replace('AA', '').replace('Ang', '')) elif 'eV' in text: wavelength = SI.extract_number(text, 'eV') else: # Now we assume there is no unit, which means it should be Angstrom wavelength = float(text) except ValueError: raise WavelengthError( f"Input '{text}' could not be identified as an wavelength") if wavelength <= 0: raise WavelengthError("Wavelength has to be positive") return wavelength
def attenuation_length(compound, density=None, natural_density=None, energy=None, wavelength=None): """ Calculates the attenuation length for a compound Transmisison if then exp(-thickness/attenuation_length) :Parameters: *compound* : Formula initializer Chemical formula. *density* : float | |g/cm^3| Mass density of the compound, or None for default. *natural_density* : float | |g/cm^3| Mass density of the compound at naturally occurring isotope abundance. *wavelength* : float or vector | |Ang| Wavelength of the X-ray. *energy* : float or vector | keV Energy of the X-ray, if *wavelength* is not specified. :Returns: *attenuation_length* : vector | |m| as function of (energy) :Notes: against http://henke.lbl.gov/optical_constants/ """ if energy is not None: wavelength = xray_wavelength(energy) assert wavelength is not None, "scattering calculation needs energy or wavelength" if (numpy.isscalar(wavelength)): wavelength = numpy.array([wavelength]) n = index_of_refraction(compound=compound, density=density, natural_density=natural_density, wavelength=wavelength) attenuation_length = (wavelength * 1e-10) / (4 * numpy.pi * numpy.imag(n)) return numpy.abs(attenuation_length)
def xafs_sample_prep_get_abslen(request): """ Computes the relevant x-ray absorption data. POSTDATA: chem: Element chemical formula. ephot: Photon energy (incoming) in keV. dens: Compound density in g/cc bn: Boron Nitride dilution fraction (between 0-1) RETURNS: X-ray data as an HTTPresponse string. """ if request.method == "POST": res = "<table class='table table-bordered'>" try: #Get POSTDATA chem = str(request.POST['chem']) ephot = float(request.POST['ephot']) dens = float(request.POST['dens']) bn = float(request.POST['bn']) except: res = "Input format error! Please fix and retry." return HttpResponse(res) #Parse formula form = formula(chem) res += "<tr><td>Compound:</td><td>" + chem + "</td></tr>" #Compute molecular mass mass = 0.0 for elem in form.atoms: mass += form.atoms[elem]*elem.mass res += "<tr><td>Molecular Mass:</td><td>" + str(round(mass,2)) + " g/mol </td></tr>" #Compute total mu mu = 0.0 r_e = 2.8179403E-13 #cm N_a = 6.02214E23 for elem in form.atoms: frac = (form.atoms[elem]*elem.mass) / mass xr = xsf.Xray(elem) xsec = 2*r_e*xsf.xray_wavelength(ephot)*1E-8*xr.scattering_factors(energy=ephot)[1]*(N_a/elem.mass) mu += frac * xsec #Perform dilution with BN if needed if str(bn) != "" and 0 < bn < 1: bn_mass = B.mass + N.mass bn_dens = 2.29 #source: Sigma-Aldrich, BN powder ~1 micron, 98% frac_b = B.mass / bn_mass frac_n = N.mass / bn_mass dens = (1 - bn) * dens + bn * bn_dens xr_B = xsf.Xray(B) xsec_B = 2*r_e*xsf.xray_wavelength(ephot)*1E-8*xr_B.scattering_factors(energy=ephot)[1]*(N_a/B.mass) xr_N = xsf.Xray(N) xsec_N = 2*r_e*xsf.xray_wavelength(ephot)*1E-8*xr_N.scattering_factors(energy=ephot)[1]*(N_a/N.mass) mu_bn = frac_b * xsec_B + frac_n * xsec_N mu = (1 - bn) * mu + bn * mu_bn res += "<tr><td>BN Dilution Fraction:</td><td>" + str(bn) + "</td></tr>" mu *= dens res += "<tr><td>Linear Absorption Coefficient:</td><td>" + str(round(mu,2)) + " 1/cm </td></tr>" #Compute absorption length abs_length= round((1/mu) * 10000, 2) #microns res += "<tr><td>Total X-ray Absorption Length:</td><td>" + str(round(abs_length,2)) + " microns </td></tr>" #Compute approx. total mass assuming 0.65 cm radius for pellet (standard size for Pike brand pellet press) total_mass = round(dens * (0.65**2) * 3.14159 * (abs_length/10000) * 1000, 2) res += "<tr><td>Pellet Mass (13mm diameter):</td><td>" + str(round(total_mass,2)) + " mg</td></tr>" res += "</table>" return HttpResponse(res) else: return HttpResponse("POSTdata must be used!")
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