Source code for physdata.star

# -*- coding: UTF-8 -*-

"""star.py: A module to interface the
`Stopping-Power & Range Tables for Electrons, Protons, and Helium Ions
<https://www.nist.gov/pml/stopping-power-range-tables-electrons-protons-and-helium-ions>`_.

"""

import requests
import re

import warnings


[docs]def fetch_estar(el_id, density=None): """ Fetch from the website the data for electrons in a medium. Check the `STAR appendix <http://physics.nist.gov/PhysRefData/Star/Text/appendix.html>`_ for further details. Args: el_id (int): The positive integer identifying the medium. density (float or bool, optional): If given, the density scaling is removed. If it is the boolean True, the density will be taken from the website. Returns: (list): a list of lists, a list with the data for each tabulated energy value, each a list with: * (float): Kinetic energy in MeV. * (float): Collision stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Radiative stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Total stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): CSDA range in g/cm^2 or in cm if a density was given. * (float): Radiation yield (fraction of kinetic energy converted into bremsstrahlung). * (float): Density effect parameter """ return _fetch_star(el_id, particle="e", density=density)
[docs]def fetch_pstar(el_id, density=None): """ Fetch from the website the data for protons in a medium. Check the `STAR appendix <http://physics.nist.gov/PhysRefData/Star/Text/appendix.html>`_ for further details. Args: el_id (int): The positive integer identifying the medium. density (float or bool, optional): If given, the density scaling is removed. If it is the boolean True, the density will be taken from the website. Returns: (list): a list of lists, a list with the data for each tabulated energy value, each a list with: * (float): Kinetic energy in MeV. * (float): Electronic stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Nuclear stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Total stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): CSDA range in g/cm^2 or in cm if a density was given. * (float): Projected CSDA range in g/cm^2 or in cm if a density was given. * (float): Detour factor (projected CSDA / CSDA). """ return _fetch_star(el_id, particle="p", density=density)
[docs]def fetch_astar(el_id, density=None): """ Fetch from the website the data for alpha particles in a medium. Check the `STAR appendix <http://physics.nist.gov/PhysRefData/Star/Text/appendix.html>`_ for further details. Args: el_id (int): The positive integer identifying the medium. density (float or bool, optional): If given, the density scaling is removed. If it is the boolean True, the density will be taken from the website. Returns: (list): a list of lists, a list with the data for each tabulated energy value, each a list with: * (float): Kinetic energy in MeV. * (float): Electronic stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Nuclear stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): Total stopping power in MeV cm^2/g or in MeV/cm if a density was given. * (float): CSDA range in g/cm^2 or in cm if a density was given. * (float): Projected CSDA range in g/cm^2 or in cm if a density was given. * (float): Detour factor (projected CSDA / CSDA). """ return _fetch_star(el_id, particle="a", density=density)
def _fetch_star(el_id, particle="e", density=None): # Note: 3 public functions are offered instead of this one because the return of estar and pstar/astar is # different. # el_id is a 3 character string in the website, so it has to converted. # Despite only int support is documented for el_id, also check for strings. if type(el_id) == int: z = str(el_id) elif (type(el_id) is not str) or not el_id.isdigit(): raise TypeError("el_id must be either a positive integer or a string with a positive integer.") else: z = el_id z = z.zfill(3) # Ensure 3 digits if particle == "e": url = 'https://physics.nist.gov/cgi-bin/Star/e_table-t.pl' data = {"matno": z, "ShowDefault": "on"} elif particle == "p": url = 'https://physics.nist.gov/cgi-bin/Star/ap_table-t.pl' data = {"matno": z, "ShowDefault": "on", "prog": "PSTAR"} elif particle == "a": url = 'https://physics.nist.gov/cgi-bin/Star/ap_table-t.pl' data = {"matno": z, "ShowDefault": "on", "prog": "ASTAR"} else: raise TypeError("particle must be a string containing either 'e', 'p' or 'a'.") try: r = requests.post(url, data=data) except requests.SSLERROR: # If a certificate error occurred, ignore the certificate r = requests.post(url, data=data, verify=False) # TODO: Catch unexisting material html = r.text number_pattern = r'-?[0-9]+\.?[0-9]*E[-+][0-9]+' if density is None: density = 1.0 elif type(density) is bool: if density: # If density is True, read from html if particle == "e": # The first scientific number is the density density = float(re.search(number_pattern, html).group(0)) else: # Density is stored in a different page html2 = requests.get('http://physics.nist.gov/cgi-bin/Star/compos.pl?ap-text' + z).text density = float(re.search(number_pattern, html2).group(0)) else: # If false, do not scale density = 1.0 elif type(density) is int: density = float(density) elif type(density) is not float or density == 0.0: raise ValueError("density must be a non 0.0 float or a bool") output = [] # Find lines with seven numbers ending in <br> # In e, all in scientific notation, in a and p the last one is a proper ratio (in (0, 1)). if particle == "e": lines = re.findall("(" + (number_pattern + " ") * 6 + number_pattern + ")" + "<br>", html) unit_scale = [1.0, density, density, density, 1 / density, 1.0, 1.0] else: # p or a lines = re.findall("(" + (number_pattern + " ") * 6 + "0.[0-9]+" + ")" + "<br>", html) unit_scale = [1.0, density, density, density, 1 / density, 1 / density, 1] for l in lines: l_float = map(float, l.split()) # Scale with the density the magnitudes that depend on it output.append(list(map(lambda a, b: a * b, l_float, unit_scale))) if not output: warnings.warn("Empty list returned. Is the NIST page working?:\n%s" % url) return output