Skip to content

element

Module for static information about chemical elements.

Element

Storage class for information about a chemical element.

Examples:

>>> h = Element.from_string("H")
>>> c = Element.from_string("C")
>>> n = Element.from_atomic_number(7)
>>> f = Element.from_string("F")

Element implements an ordering for sorting in e.g. molecular formulae where carbon and hydrogen come first, otherwise elements are sorted in order of atomic number.

>>> sorted([h, f, f, c, n])
[C, H, N, F, F]
Source code in chmpy/core/element.py
@functools.total_ordering
class Element(metaclass=_ElementMeta):
    """Storage class for information about a chemical element.

    Examples:
        >>> h = Element.from_string("H")
        >>> c = Element.from_string("C")
        >>> n = Element.from_atomic_number(7)
        >>> f = Element.from_string("F")

        Element implements an ordering for sorting in e.g.
        molecular formulae where carbon and hydrogen come first,
        otherwise elements are sorted in order of atomic number.

        >>> sorted([h, f, f, c, n])
        [C, H, N, F, F]
    """

    def __init__(self, atomic_number, name, symbol, cov, vdw, mass):
        """Initialize an Element from its chemical data."""
        self.atomic_number = atomic_number
        self.name = name
        self.symbol = symbol
        self.cov = cov
        self.vdw = vdw
        self.mass = mass

    @staticmethod
    def from_string(s: str) -> "Element":
        """Create an element from a given element symbol.

        Args:
            s (str): a string representation of an element in the periodic table

        Returns:
            Element: an Element object if the conversion was successful, otherwise an exception is raised

        Examples:
            >>> Element.from_string("h")
            H
            >>> Element["rn"].name
            'radon'
            >>> Element["AC"].cov
            2.15
        """
        symbol = s.strip().capitalize()
        if symbol == "D":
            symbol = "H"
        if symbol.isdigit():
            return Element.from_atomic_number(int(symbol))
        if symbol not in _EL_FROM_SYM:
            name = symbol.lower()
            if name not in _EL_FROM_NAME:
                return Element.from_label(s)
            else:
                return Element(*_EL_FROM_NAME[name])
        return Element(*_EL_FROM_SYM[symbol])

    @staticmethod
    def from_label(label: str) -> "Element":
        """Create an element from a label e.g. 'C1', 'H2_F2___i' etc.

        Args:
            l (str): a string representation of an element in the periodic table

        Returns:
            Element: an Element object if the conversion was successful, otherwise an exception is raised

        Examples:
            >>> Element.from_label("C1")
            C
            >>> Element.from_label("H")
            H
            >>> Element["LI2_F2____1____i"]
            Li

            An ambiguous case, will make this Calcium not Carbon
            >>> Element.from_label("Ca2_F2____1____i")
            Ca
        """
        m = re.match(_SYMBOL_REGEX, label)
        if m is None:
            raise ValueError("Could not determine symbol from {}".format(label))
        sym = m.group(1).strip().capitalize()
        if sym not in _EL_FROM_SYM:
            raise ValueError("Could not determine symbol from {}".format(label))
        return Element(*_EL_FROM_SYM[sym])

    @staticmethod
    def from_atomic_number(n: int) -> "Element":
        """Create an element from a given atomic number.

        Args:
            n (int): the atomic number of the element

        Returns:
            Element: an Element object if atomic number was valid, otherwise an exception is raised

        Examples:
            >>> Element.from_atomic_number(2)
            He
            >>> Element[79].name
            'gold'
        """
        return Element(n, *_ELEMENT_DATA[n - 1])

    @property
    def vdw_radius(self) -> float:
        """The van der Waals radius in angstroms."""
        return self.vdw

    @property
    def color(self):
        """The color RGBA color of this element."""
        return _EL_COLORS[self.atomic_number - 1]

    @property
    def ball_stick_radius(self) -> float:
        """The radius of this element in a ball and stick representation."""
        if self.symbol == "H":
            return self.covalent_radius
        return self.cov * 0.5

    @property
    def covalent_radius(self) -> float:
        """The covalent radius in angstroms."""
        return self.cov

    def __repr__(self):
        """Represent this element as a string for REPL."""
        return self.symbol

    def __hash__(self):
        """Hash of this element (its atomic number)."""
        return int(self.atomic_number)

    def _is_valid_operand(self, other):
        return hasattr(other, "atomic_number")

    def __eq__(self, other):
        """Check if two Elements have the same atomic number."""
        if not self._is_valid_operand(other):
            raise NotImplementedError
        return self.atomic_number == other.atomic_number

    def __lt__(self, other):
        """Check which element comes before the other in chemical formulae (C first, then order of atomic number)."""
        if not self._is_valid_operand(other):
            raise NotImplementedError
        n1, n2 = self.atomic_number, other.atomic_number
        if n1 == n2:
            return False
        if n1 == 6:
            return True
        elif n2 == 6:
            return False
        else:
            return n1 < n2

ball_stick_radius: float property

The radius of this element in a ball and stick representation.

color property

The color RGBA color of this element.

covalent_radius: float property

The covalent radius in angstroms.

vdw_radius: float property

The van der Waals radius in angstroms.

__eq__(other)

Check if two Elements have the same atomic number.

Source code in chmpy/core/element.py
def __eq__(self, other):
    """Check if two Elements have the same atomic number."""
    if not self._is_valid_operand(other):
        raise NotImplementedError
    return self.atomic_number == other.atomic_number

__hash__()

Hash of this element (its atomic number).

Source code in chmpy/core/element.py
def __hash__(self):
    """Hash of this element (its atomic number)."""
    return int(self.atomic_number)

__init__(atomic_number, name, symbol, cov, vdw, mass)

Initialize an Element from its chemical data.

Source code in chmpy/core/element.py
def __init__(self, atomic_number, name, symbol, cov, vdw, mass):
    """Initialize an Element from its chemical data."""
    self.atomic_number = atomic_number
    self.name = name
    self.symbol = symbol
    self.cov = cov
    self.vdw = vdw
    self.mass = mass

__lt__(other)

Check which element comes before the other in chemical formulae (C first, then order of atomic number).

Source code in chmpy/core/element.py
def __lt__(self, other):
    """Check which element comes before the other in chemical formulae (C first, then order of atomic number)."""
    if not self._is_valid_operand(other):
        raise NotImplementedError
    n1, n2 = self.atomic_number, other.atomic_number
    if n1 == n2:
        return False
    if n1 == 6:
        return True
    elif n2 == 6:
        return False
    else:
        return n1 < n2

__repr__()

Represent this element as a string for REPL.

Source code in chmpy/core/element.py
def __repr__(self):
    """Represent this element as a string for REPL."""
    return self.symbol

from_atomic_number(n) staticmethod

Create an element from a given atomic number.

Parameters:

Name Type Description Default
n int

the atomic number of the element

required

Returns:

Name Type Description
Element Element

an Element object if atomic number was valid, otherwise an exception is raised

Examples:

>>> Element.from_atomic_number(2)
He
>>> Element[79].name
'gold'
Source code in chmpy/core/element.py
@staticmethod
def from_atomic_number(n: int) -> "Element":
    """Create an element from a given atomic number.

    Args:
        n (int): the atomic number of the element

    Returns:
        Element: an Element object if atomic number was valid, otherwise an exception is raised

    Examples:
        >>> Element.from_atomic_number(2)
        He
        >>> Element[79].name
        'gold'
    """
    return Element(n, *_ELEMENT_DATA[n - 1])

from_label(label) staticmethod

Create an element from a label e.g. 'C1', 'H2_F2___i' etc.

Parameters:

Name Type Description Default
l str

a string representation of an element in the periodic table

required

Returns:

Name Type Description
Element Element

an Element object if the conversion was successful, otherwise an exception is raised

Examples:

>>> Element.from_label("C1")
C
>>> Element.from_label("H")
H
>>> Element["LI2_F2____1____i"]
Li

An ambiguous case, will make this Calcium not Carbon

>>> Element.from_label("Ca2_F2____1____i")
Ca
Source code in chmpy/core/element.py
@staticmethod
def from_label(label: str) -> "Element":
    """Create an element from a label e.g. 'C1', 'H2_F2___i' etc.

    Args:
        l (str): a string representation of an element in the periodic table

    Returns:
        Element: an Element object if the conversion was successful, otherwise an exception is raised

    Examples:
        >>> Element.from_label("C1")
        C
        >>> Element.from_label("H")
        H
        >>> Element["LI2_F2____1____i"]
        Li

        An ambiguous case, will make this Calcium not Carbon
        >>> Element.from_label("Ca2_F2____1____i")
        Ca
    """
    m = re.match(_SYMBOL_REGEX, label)
    if m is None:
        raise ValueError("Could not determine symbol from {}".format(label))
    sym = m.group(1).strip().capitalize()
    if sym not in _EL_FROM_SYM:
        raise ValueError("Could not determine symbol from {}".format(label))
    return Element(*_EL_FROM_SYM[sym])

from_string(s) staticmethod

Create an element from a given element symbol.

Parameters:

Name Type Description Default
s str

a string representation of an element in the periodic table

required

Returns:

Name Type Description
Element Element

an Element object if the conversion was successful, otherwise an exception is raised

Examples:

>>> Element.from_string("h")
H
>>> Element["rn"].name
'radon'
>>> Element["AC"].cov
2.15
Source code in chmpy/core/element.py
@staticmethod
def from_string(s: str) -> "Element":
    """Create an element from a given element symbol.

    Args:
        s (str): a string representation of an element in the periodic table

    Returns:
        Element: an Element object if the conversion was successful, otherwise an exception is raised

    Examples:
        >>> Element.from_string("h")
        H
        >>> Element["rn"].name
        'radon'
        >>> Element["AC"].cov
        2.15
    """
    symbol = s.strip().capitalize()
    if symbol == "D":
        symbol = "H"
    if symbol.isdigit():
        return Element.from_atomic_number(int(symbol))
    if symbol not in _EL_FROM_SYM:
        name = symbol.lower()
        if name not in _EL_FROM_NAME:
            return Element.from_label(s)
        else:
            return Element(*_EL_FROM_NAME[name])
    return Element(*_EL_FROM_SYM[symbol])

chemical_formula(elements, subscript=False)

Calculate the chemical formula for the given list of elements.

Examples:

>>> chemical_formula(['O', 'C', 'O'])
'CO2'
>>> chemical_formula(['C', 'H', 'O', 'B'])
'BCHO'

Parameters:

Name Type Description Default
elements List[Element or str]

a list of elements or element symbols. Note that if a list of strings are provided the order of chemical symbols may not match convention.

required
subscript (bool, optoinal)

toggle to use unicode subscripts for the chemical formula string

False

Returns:

Name Type Description
str

the chemical formula

Source code in chmpy/core/element.py
def chemical_formula(elements, subscript=False):
    """Calculate the chemical formula for the given list of elements.

    Examples:
        >>> chemical_formula(['O', 'C', 'O'])
        'CO2'
        >>> chemical_formula(['C', 'H', 'O', 'B'])
        'BCHO'

    Args:
        elements (List[Element or str]): a list of elements or element symbols.
            Note that if a list of strings are provided the order of chemical
            symbols may not match convention.
        subscript (bool, optoinal): toggle to use unicode subscripts for the chemical formula string

    Returns:
        str: the chemical formula
    """
    count = Counter(sorted(elements))
    if subscript:
        blocks = []
        for el, c in count.items():
            c = "".join(chr(0x2080 + int(i)) for i in str(c)) if c > 1 else ""
            blocks.append(f"{el}{c}")
    else:
        blocks = []
        for el, c in count.items():
            c = c if c > 1 else ""
            blocks.append(f"{el}{c}")
    return "".join(blocks)

cov_radii(atomic_numbers)

Return the covalent radii for the given atomic numbers.

Parameters:

Name Type Description Default
atomic_numbers array_like

the (N,) length integer array of atomic numbers

required

Returns:

Type Description

np.ndarray: (N,) array of floats representing covalent radii

Source code in chmpy/core/element.py
def cov_radii(atomic_numbers):
    """Return the covalent radii for the given atomic numbers.

    Args:
        atomic_numbers (array_like): the (N,) length integer array of atomic numbers

    Returns:
        np.ndarray: (N,) array of floats representing covalent radii
    """
    if np.any(atomic_numbers < 1) or np.any(atomic_numbers > 103):
        raise ValueError("All elements must be atomic numbers between [1,103]")
    return np.array([_ELEMENT_DATA[i - 1][2] for i in atomic_numbers], dtype=np.float32)

element_names(atomic_numbers)

Return the element names for the given atomic numbers.

Parameters:

Name Type Description Default
atomic_numbers array_like

the (N,) length integer array of atomic numbers

required

Returns:

Type Description

List[str]: (N,) list of strings representing element names

Source code in chmpy/core/element.py
def element_names(atomic_numbers):
    """Return the element names for the given atomic numbers.

    Args:
        atomic_numbers (array_like): the (N,) length integer array of atomic numbers

    Returns:
        List[str]: (N,) list of strings representing element names
    """
    if np.any(atomic_numbers < 1) or np.any(atomic_numbers > 103):
        raise ValueError("All elements must be atomic numbers between [1,103]")
    return [_ELEMENT_DATA[i - 1][0] for i in atomic_numbers]

element_symbols(atomic_numbers)

Return the element symbols for the given atomic numbers.

Parameters:

Name Type Description Default
atomic_numbers array_like

the (N,) length integer array of atomic numbers

required

Returns:

Type Description

List[str]: (N,) list of strings representing element symbols

Source code in chmpy/core/element.py
def element_symbols(atomic_numbers):
    """Return the element symbols for the given atomic numbers.

    Args:
        atomic_numbers (array_like): the (N,) length integer array of atomic numbers

    Returns:
        List[str]: (N,) list of strings representing element symbols
    """
    if np.any(atomic_numbers < 1) or np.any(atomic_numbers > 103):
        raise ValueError("All elements must be atomic numbers between [1,103]")
    return [_ELEMENT_DATA[i - 1][1] for i in atomic_numbers]

vdw_radii(atomic_numbers)

Return the van der Waals radii for the given atomic numbers.

Parameters:

Name Type Description Default
atomic_numbers array_like

the (N,) length integer array of atomic numbers

required

Returns:

Type Description

np.ndarray: (N,) array of floats representing van der Waals radii

Source code in chmpy/core/element.py
def vdw_radii(atomic_numbers):
    """Return the van der Waals radii for the given atomic numbers.

    Args:
        atomic_numbers (array_like): the (N,) length integer array of atomic numbers

    Returns:
        np.ndarray: (N,) array of floats representing van der Waals radii
    """
    if np.any(atomic_numbers < 1) or np.any(atomic_numbers > 103):
        raise ValueError("All elements must be atomic numbers between [1,103]")
    return np.array([_ELEMENT_DATA[i - 1][3] for i in atomic_numbers], dtype=np.float32)