Esempio n. 1
0
def element_from_name(name):
    """Search for an element by its name

    Look up an element from a list of known elements by name.

    Parameters
    ----------
    name : str
        Element name to look for, digits and spaces are removed before search

    Returns
    -------
    matched_element : element.Element
        The matching element from the periodic table

    Raises
    ------
    ElementError
        If no match is found
    """
    if not isinstance(name, str):
        raise TypeError(
            f"`string` ({name}) must be a string.  Provided {type(name).__name__}."
        )

    name = name.lower()
    matched_element = name_dict.get(name)
    if matched_element is None:
        raise ElementError(f"No element with name {name}")

    return matched_element
Esempio n. 2
0
def element_from_atomic_number(atomic_number):
    """Search for an element by its atomic number

    Look up an element from a list of known elements by atomic number.

    Parameters
    ----------
    atomic_number : int
        Element atomic number

    Returns
    -------
    matched_element : element.Element
        The matching element from the periodic table

    Raises
    ------
    ElementError
        If no match is found
    """
    if not isinstance(atomic_number, int):
        raise TypeError(
            f"`string` ({atomic_number}) must be an integer.  Provided {type(atomic_number).__name__}."
        )

    matched_element = atomic_dict.get(atomic_number)
    if matched_element is None:
        raise ElementError(f"No element with atomic number {atomic_number}")

    return matched_element
Esempio n. 3
0
def element_from_symbol(symbol):
    """Search for an element by its symbol

    Look up an element from a list of known elements by symbol.

    Parameters
    ----------
    symbol : str
        Element symbol

    Returns
    -------
    matched_element : element.Element
        The matching element from the periodic table

    Raises
    ------
    ElementError
        If no match is found
    """
    if not isinstance(symbol, str):
        raise TypeError(
            f"`string` ({symbol}) must be a string.  Provided {type(symbol).__name__}."
        )

    symbol = symbol.capitalize()
    matched_element = symbol_dict.get(symbol)
    if matched_element is None:
        raise ElementError(f"No element with symbol {symbol}")

    return matched_element
Esempio n. 4
0
def element_from_mass(mass, exact=True, duplicates="error"):
    """Search for an element by its mass

    Look up an element from a list of known elements by mass (amu).
    By default, requires that the element mass match exactly
    to the first digit after the decimal. Using `exact=False`
    will switch this behavior to return the element with the
    closest mass.

    Parameters
    ----------
    mass : int, float
        Element mass in amu
    exact : bool, optional,  default=True
        Require that the mass match to the first decimal. If False, the
        element with the closest mass will be returned
    duplicates : enum, optional, default="error"
        How to handle duplicate elements with the same mass.
        Error ("error"), return a tuple ("all"), or return
        None ("none")

    Returns
    -------
    matched_element : element.Element or tuple of element.Element
        The matching element(s) from the periodic table
    """
    if not isinstance(mass, (float, int)):
        raise TypeError("`mass` ({mass}) must be a float")

    if duplicates.lower() not in ["error", "all", "none"]:
        raise TypeError(
            "`duplicates` must be one of the following: `error`, `all`, `none`"
        )
    mass = round(float(mass), 1)

    if exact:
        # Exact search mode
        matched_element = mass_dict.get(mass)
    else:
        # Closest match mode
        mass_closest = min(mass_dict.keys(), key=lambda k: abs(k - mass))
        msg = "Closest mass to {}: {}".format(mass, mass_closest)
        warnings.warn(msg)
        matched_element = mass_dict.get(mass_closest)

    if matched_element is None:
        raise ElementError(f"No element with mass {mass}")

    if len(matched_element) == 1:
        matched_element = matched_element[0]
    else:
        if duplicates.lower() == "error":
            raise MultiMatchError(
                f"Multiple elements have mass {mass}: {matched_element}")
        elif duplicates.lower() == "all":
            matched_element = tuple(matched_element)
        elif duplicates.lower() == "none":
            matched_element = None

    return matched_element
Esempio n. 5
0
def element_from_name(name):
    """Search for an element by its name

    Look up an element from a list of known elements by name.
    Return None if no match found.

    Parameters
    ----------
    name : str
        Element name to look for, digits and spaces are removed before search

    Returns
    -------
    matched_element : element.Element
        Return an element from the periodic table if the name is found,
        otherwise return None
    """
    if not isinstance(name, str):
        raise TypeError("`name` ({name}) must be a string")

    name = name.lower()
    matched_element = name_dict.get(name)
    if matched_element is None:
        raise ElementError(f"No element with name {name}")

    return matched_element
Esempio n. 6
0
def element_from_symbol(symbol):
    """Search for an element by its symbol

    Look up an element from a list of known elements by symbol.
    Return None if no match found.

    Parameters
    ----------
    symbol : str
        Element symbol

    Returns
    -------
    matched_element : element.Element
        Return an element from the periodic table if the symbol is found,
        otherwise return None
    """
    if not isinstance(symbol, str):
        raise TypeError("`symbol` ({symbol}) must be a string")

    symbol = symbol.capitalize()
    matched_element = symbol_dict.get(symbol)
    if matched_element is None:
        raise ElementError(f"No element with symbol {symbol}")

    return matched_element
Esempio n. 7
0
def element_from_atomic_number(atomic_number):
    """Search for an element by its atomic number

    Look up an element from a list of known elements by atomic number.

    Parameters
    ----------
    atomic_number : int
        Element atomic number

    Returns
    -------
    matched_element : element.Element
        Return an element from the periodic table if we find a match,
    """
    if not isinstance(atomic_number, int):
        raise TypeError("`atomic_number` ({atomic_number}) must be an int")

    matched_element = atomic_dict.get(atomic_number)
    if matched_element is None:
        raise ElementError(f"No element with atomic number {atomic_number}")

    return matched_element
Esempio n. 8
0
def infer_element_from_string(string):
    """Attempt to infer an element from a string

    First checks if the string matches a two-character
    element symbol. If not, checks if the string matches
    an element name.

    Parameters
    ----------
    string : str
        String to attempt element inference from

    Returns
    -------
    matched_element : element.Element
        The matching element from the periodic table

    Raises
    ------
    ElementError
        If no match is found
    """
    if not isinstance(string, str):
        raise TypeError(
            f"`string` ({string}) must be a string.  Provided {type(string).__name__}"
        )

    try:
        matched_element = element_from_symbol(string)
    except ElementError:
        try:
            matched_element = element_from_name(string)
        except ElementError:
            raise ElementError(
                f"Unable to match {string} with element name or symbol")

    return matched_element