Extensible periodic table of the elements with support for mass, density and X-ray/neutron scattering information
—
Core functionality for accessing elements, isotopes, and ions from the periodic table with comprehensive property data including mass, density, atomic structure, and specialized scientific properties.
Access elements from the periodic table using atomic number, symbol, or name with comprehensive property data loaded on demand.
def __getitem__(self, atomic_number: int) -> Element:
"""
Get element by atomic number.
Args:
atomic_number: Atomic number (1-118)
Returns:
Element instance
"""
def symbol(self, symbol: str) -> Element:
"""
Lookup element by chemical symbol.
Args:
symbol: Chemical symbol (e.g., 'Fe', 'Ni', 'H')
Returns:
Element instance
"""
def name(self, name: str) -> Element:
"""
Lookup element by name.
Args:
name: Element name (e.g., 'iron', 'nickel', 'hydrogen')
Returns:
Element instance
"""
def isotope(self, isotope_str: str) -> Isotope:
"""
Lookup isotope by string specification.
Args:
isotope_str: Isotope string (e.g., '56-Fe', '58-Ni')
Returns:
Isotope instance
"""Usage examples:
import periodictable as pt
# Different ways to access iron
fe1 = pt.elements[26] # By atomic number
fe2 = pt.elements.Fe # By symbol attribute
fe3 = pt.elements.symbol('Fe') # By symbol method
fe4 = pt.elements.name('iron') # By name method
# Access specific isotopes
fe56 = pt.elements.isotope('56-Fe') # Iron-56
ni58 = pt.elements.isotope('58-Ni') # Nickel-58
# Special isotopes available directly
deuterium = pt.D # Deuterium (2-H)
tritium = pt.T # Tritium (3-H)Each element provides core properties and access to isotopes and ions with lazy loading for specialized data.
class Element:
"""Individual element with properties and access to isotopes/ions."""
# Core properties (always available)
symbol: str # Chemical symbol (e.g., 'Fe')
name: str # Element name (e.g., 'iron')
number: int # Atomic number
mass: float # Atomic mass in u
mass_units: str # Units for mass (typically 'u')
density: float # Density at STP in g/cm³
density_units: str # Units for density
# Container properties
isotopes: dict # Available isotopes
ions: dict # Available ions
def __getitem__(self, mass_number: int) -> Isotope:
"""Get isotope by mass number."""
def add_isotope(self, mass_number: int) -> Isotope:
"""Add new isotope with given mass number."""
@property
def ion(self) -> dict:
"""Access ions via element.ion[charge]."""Lazy-loaded properties (loaded when first accessed):
# Structural properties
covalent_radius: float # Covalent radius for bonding
covalent_radius_units: str # Units for covalent radius
covalent_radius_uncertainty: float # Uncertainty in covalent radius
crystal_structure: str # Crystal lattice structure
# Scattering properties
neutron: Neutron # Neutron scattering data
xray: Xray # X-ray scattering data
# Spectroscopic properties
K_alpha: float # K-alpha X-ray line wavelength
K_beta1: float # K-beta1 X-ray line wavelength
K_alpha_units: str # Units for K-alpha
K_beta1_units: str # Units for K-beta1
# Magnetic properties
magnetic_ff: dict # Magnetic form factors
# Nuclear properties (isotopes only)
neutron_activation: dict # Neutron activation dataUsage examples:
import periodictable as pt
# Basic element properties
iron = pt.Fe
print(f"Symbol: {iron.symbol}") # Fe
print(f"Name: {iron.name}") # iron
print(f"Atomic number: {iron.number}") # 26
print(f"Mass: {iron.mass} {iron.mass_units}") # Mass in atomic mass units
print(f"Density: {iron.density} {iron.density_units}") # g/cm³
# Lazy-loaded properties (trigger data loading)
print(f"Covalent radius: {iron.covalent_radius} {iron.covalent_radius_units}")
print(f"Crystal structure: {iron.crystal_structure}")
# Check if neutron data is available
if hasattr(iron, 'neutron') and iron.neutron:
sld = iron.neutron.sld()
print(f"Neutron SLD: {sld}")Access specific isotopes with detailed nuclear and scattering properties beyond the natural abundance data.
class Isotope(Element):
"""Element isotope with specific mass number."""
# Isotope-specific properties
isotope: int # Mass number
abundance: float # Natural abundance (if available)
# Nuclear properties (when available)
nuclear_spin: float # Nuclear spin quantum number
magnetic_moment: float # Nuclear magnetic moment
@property
def ion(self) -> dict:
"""Access ions of this isotope via isotope.ion[charge]."""Usage examples:
import periodictable as pt
# Access isotopes
iron56 = pt.Fe[56] # Iron-56
nickel58 = pt.Ni[58] # Nickel-58
# Isotope properties
print(f"Isotope: {iron56.isotope}") # 56
print(f"Mass: {iron56.mass}") # Isotope-specific mass
# Nuclear properties (if available)
if hasattr(iron56, 'abundance'):
print(f"Natural abundance: {iron56.abundance}%")
# Neutron scattering for isotopes
if hasattr(iron56, 'neutron') and iron56.neutron:
b_coh = iron56.neutron.b_c
print(f"Coherent scattering length: {b_coh} fm")Access charged states of elements and isotopes with mass corrections for electron loss/gain.
class Ion(Element):
"""Charged element or isotope."""
charge: int # Ion charge (positive for cations, negative for anions)
@property
def mass(self) -> float:
"""Mass adjusted for electron mass based on charge."""Usage examples:
import periodictable as pt
# Access ions
fe2_ion = pt.Fe.ion[2] # Fe²⁺ cation
fe3_ion = pt.Fe.ion[3] # Fe³⁺ cation
cl_ion = pt.Cl.ion[-1] # Cl⁻ anion
# Ion properties
print(f"Charge: {fe2_ion.charge}") # 2
print(f"Mass: {fe2_ion.mass}") # Mass corrected for electrons
# Isotope ions
fe56_2plus = pt.Fe[56].ion[2] # ⁵⁶Fe²⁺
print(f"Isotope: {fe56_2plus.isotope}") # 56
print(f"Charge: {fe56_2plus.charge}") # 2Iterate through elements and create formatted property tables for data exploration and analysis.
def __iter__(self) -> Iterator[Element]:
"""Iterate through all elements in atomic number order."""
def list(self, *props, **kwargs) -> None:
"""
Print formatted table of element properties.
Args:
*props: Property names to display
**kwargs: Formatting options
"""Usage examples:
import periodictable as pt
# Iterate through all elements
for element in pt.elements:
print(f"{element.number:3d} {element.symbol:2s} {element.name}")
# Create property tables
pt.elements.list('mass', 'density') # Mass and density table
pt.elements.list('symbol', 'covalent_radius') # Covalent radius table
# Filter elements (first 20)
for element in list(pt.elements)[:20]:
if element.density:
print(f"{element.symbol}: {element.density} g/cm³")Utility functions to test the type of atomic objects for safe property access and method dispatch.
def isatom(val) -> bool:
"""Test if value is any atomic object (element, isotope, or ion)."""
def iselement(val) -> bool:
"""Test if value is an element (not isotope or ion)."""
def isisotope(val) -> bool:
"""Test if value is an isotope."""
def ision(val) -> bool:
"""Test if value is an ion."""Usage examples:
import periodictable as pt
from periodictable.core import isatom, iselement, isisotope, ision
# Test different atomic objects
iron = pt.Fe
iron56 = pt.Fe[56]
iron2_ion = pt.Fe.ion[2]
print(isatom(iron)) # True - all atoms
print(isatom(iron56)) # True
print(isatom(iron2_ion)) # True
print(iselement(iron)) # True - element only
print(iselement(iron56)) # False - isotope
print(iselement(iron2_ion)) # False - ion
print(isisotope(iron56)) # True - isotope
print(isisotope(iron)) # False - element
print(ision(iron2_ion)) # True - ion
print(ision(iron)) # False - elementclass PeriodicTable:
"""Container for all elements, isotopes, and ions."""
def __getitem__(self, key: int) -> Element: ...
def __iter__(self) -> Iterator[Element]: ...
def symbol(self, symbol: str) -> Element: ...
def name(self, name: str) -> Element: ...
def isotope(self, isotope_str: str) -> Isotope: ...
def list(self, *props, **kwargs) -> None: ...
class Element:
"""Individual element with properties and access to isotopes/ions."""
symbol: str
name: str
number: int
mass: float
mass_units: str
density: float
density_units: str
isotopes: dict
ions: dict
def __getitem__(self, mass_number: int) -> Isotope: ...
def add_isotope(self, mass_number: int) -> Isotope: ...
@property
def ion(self) -> dict: ...
class Isotope(Element):
"""Element isotope with specific mass number."""
isotope: int
abundance: float
nuclear_spin: float
magnetic_moment: float
class Ion(Element):
"""Charged element or isotope."""
charge: int
@property
def mass(self) -> float: ...Install with Tessl CLI
npx tessl i tessl/pypi-periodictable