Chemical Properties

Several packages exist that allow us to automatically retrieve material properties of particular elements and compounds as well as relating them to the periodic table.

Being able to look up the material properties of chemicals in a one piece generative document workflow allows creators of materials to generate factually correct statements directly from looked up object properties and present those as part of the materials.

For learners in an interactive notebook, the ability to lookup and reference elements allows them to check their understanding and explore the properties of elements that have not been directly referenced in the materials.

The availability of a Periodic Table display with scripted styling means that authors can easily create views over the periodic table that highlight specific concerns, and learners can visually explore properties and patterns of elements in the periodic table context for themselves.

chemlib

chemlib is a Python package providing a wide range of functions for looking up simple chemical properties and working with simple reactions.

Reference: H. R. Ambethkar, chemlib - A Python chemistry library , 2020– . Available at: https://github.com/harirakul/chemlib.

from chemlib import Element

silicon = Element('Si')
silicon.properties
{'Unnamed: 0': 13,
 'AtomicNumber': 14.0,
 'Element': 'Silicon',
 'Symbol': 'Si',
 'AtomicMass': 28.086,
 'Neutrons': 14.0,
 'Protons': 14.0,
 'Electrons': 14.0,
 'Period': 3.0,
 'Group': 14.0,
 'Phase': 'solid',
 'Radioactive': False,
 'Natural': True,
 'Metal': False,
 'Nonmetal': False,
 'Metalloid': True,
 'Type': 'Metalloid',
 'AtomicRadius': '1.5',
 'Electronegativity': 1.9,
 'FirstIonization': '8.1517',
 'Density': '2.33',
 'MeltingPoint': '1683.15',
 'BoilingPoint': '3538',
 'Isotopes': 8.0,
 'Discoverer': 'Berzelius',
 'Year': '1824',
 'SpecificHeat': '0.705',
 'Shells': 3.0,
 'Valence': 4.0,
 'Config': '[Ne] 3s2 3p2',
 'MassNumber': 28.0}

A simple pandas dataframe summarising the periodic table properties of each element is also available as a summary table of this data over all elements:

from chemlib import chemistry

chemistry.pte.head()
Unnamed: 0 AtomicNumber Element Symbol AtomicMass Neutrons Protons Electrons Period Group ... MeltingPoint BoilingPoint Isotopes Discoverer Year SpecificHeat Shells Valence Config MassNumber
0 0 1.0 Hydrogen H 1.007 0.0 1.0 1.0 1.0 1.0 ... 14.175 20.28 3.0 Cavendish 1766 14.304 1.0 1.0 1s1 1.0
1 1 2.0 Helium He 4.002 2.0 2.0 2.0 1.0 18.0 ... Unknown 4.22 5.0 Janssen 1868 5.193 1.0 0.0 1s2 4.0
2 2 3.0 Lithium Li 6.941 4.0 3.0 3.0 2.0 1.0 ... 453.85 1615 5.0 Arfvedson 1817 3.582 2.0 1.0 [He] 2s1 7.0
3 3 4.0 Beryllium Be 9.012 5.0 4.0 4.0 2.0 2.0 ... 1560.15 2742 6.0 Vaulquelin 1798 1.825 2.0 2.0 [He] 2s2 9.0
4 4 5.0 Boron B 10.811 6.0 5.0 5.0 2.0 13.0 ... 2573.15 4200 6.0 Gay-Lussac 1808 1.026 2.0 3.0 [He] 2s2 2p1 11.0

5 rows × 31 columns

from chemlib import Compound

water = Compound("H2O")
water.coefficient, water.elements, water.formula, water.get_amounts(grams = 2), \
water.get_amounts(molecules = 2e+24), \
water.molar_mass(), water.occurences, water.percentage_by_mass('H')
(1,
 [<chemlib.chemistry.Element at 0x1189c20d0>,
  <chemlib.chemistry.Element at 0x1189c2490>,
  <chemlib.chemistry.Element at 0x1189c25b0>],
 'H₂O₁',
 {'grams': 2, 'molecules': 6.685e+22, 'moles': 0.111},
 {'molecules': 2e+24, 'moles': 3.322, 'grams': 59.829},
 18.01,
 {'H': 2, 'O': 1},
 11.183)
#Get the empirical formula of a compound that is composed of 80.6% C, and 19.4% H by mass:

from chemlib import empirical_formula_by_percent_comp as efbpc
efbpc(C = 80.6, H = 19.4)
'C1H3'
from chemlib import Compound, Reaction

N2O5 = Compound("N2O5")
H2O = Compound("H2O")
HNO3 = Compound("HNO3")
r = Reaction([N2O5, H2O], [HNO3])
r.formula, r.is_balanced, r.balance(), r.formula
('1N₂O₅ + 1H₂O₁ --> 1H₁N₁O₃', False, None, '1N₂O₅ + 1H₂O₁ --> 2H₁N₁O₃')
r.coefficients, r.constituents
({'N₂O₅': 1, 'H₂O₁': 1, 'H₁N₁O₃': 2}, ['N₂O₅', 'H₂O₁', 'H₁N₁O₃'])
subscript = str.maketrans("₀₁₂₃₄₅₆₇₈₉", "0123456789")

r.product_formulas[0].translate(subscript)
'H1N1O3'
r.reactant_formulas, r.product_formulas
(['N₂O₅', 'H₂O₁'], ['H₁N₁O₃', 'H₁N₁O₃'])
from chemlib import Compound, Combustion

methane = Compound('CH4')
c = Combustion(methane)
c.formula, c.is_balanced
('1C₁H₄ + 2O₂ --> 2H₂O₁ + 1C₁O₂', True)
c.formula, c.is_balanced
('1C₁H₄ + 2O₂ --> 2H₂O₁ + 1C₁O₂', True)
#Currently broken
#from chemlib import Galvanic_Cell
#g = Galvanic_Cell("Pb", "Zn")

pymatgen

The pymatgen (Python Materials Genomics) provides a wide range of utilities to support materials analysis.

Let’s begin by importing the package:

import pymatgen.core as mgc

We can look up various properties of an individual element directly:

si = mgc.Element('Si')

si.atomic_mass, si.melting_point, si.boiling_point
(28.0855, 1687.0, 3173.0)

We can also return Boolean flags that describe vrious other properties of a particular element. Such flags could trivially be used as part of a simple quiz, for example.

for p in ['alkali', 'halogen', 'lanthanoid', 'metalloid', 'noble_gas', 'quadrupolar', \
    'rare_earth_metal', 'transition_metal']:
    print(f"{p}: {getattr(si, 'is_'+p)}")
alkali: False
halogen: False
lanthanoid: False
metalloid: True
noble_gas: False
quadrupolar: False
rare_earth_metal: False
transition_metal: False

Valence properties as well as periodci table group and row number can be returned for each element:

si.value, si.valence, si.row, si.number, si.group
('Si', (1, 2), 3, 14, 14)

We can also retrieve the electronic structure of an element:

si.full_electronic_structure
[(1, 's', 2), (2, 's', 2), (2, 'p', 6), (3, 's', 2), (3, 'p', 2)]

As well as element lookups, we can also look-up properties of compounds based on their formula:

comp = mgc.Composition('Fe2O3')

for p in ['is_element', 'weight','num_atoms', 'elements']:
    print(f"{p}: {getattr(comp, p)}")
is_element: False
weight: 159.6882 amu
num_atoms: 5.0
elements: [Element Fe, Element O]

We can also explore variants on the formula:

for f in ["formula", "alphabetical_formula", "reduced_formula",
          "hill_formula","element_composition",  "reduced_composition"]:
    print(f"{f}: {getattr(comp, f)}")
formula: Fe2 O3
alphabetical_formula: Fe2 O3
reduced_formula: Fe2O3
hill_formula: Fe2 O3
element_composition: Fe2 O3
reduced_composition: Fe2 O3

We can also lookup the compostion of the compound:

comp.fractional_composition,  comp.get_atomic_fraction('Fe'),  comp.get_atomic_fraction('O')
(Comp: Fe0.4 O0.6, 0.4, 0.6)

The compound weight and basic electron structure can also be described:

comp.total_electrons, comp.weight
(76.0, 159.6882)

As well as individual elements and compounds, we can preview a simple text view of the periodic table:

mgc.Element.print_periodic_table()
H                                                                   He 
Li  Be                                          B   C   N   O   F   Ne 
Na  Mg                                          Al  Si  P   S   Cl  Ar 
K   Ca  Sc  Ti  V   Cr  Mn  Fe  Co  Ni  Cu  Zn  Ga  Ge  As  Se  Br  Kr 
Rb  Sr  Y   Zr  Nb  Mo  Tc  Ru  Rh  Pd  Ag  Cd  In  Sn  Sb  Te  I   Xe 
Cs  Ba      Hf  Ta  W   Re  Os  Ir  Pt  Au  Hg  Tl  Pb  Bi  Po  At  Rn 
Fr  Ra      Rf  Db  Sg  Bh  Hs  Mt  Ds  Rg  Cn  Nh  Fl  Mc  Lv  Ts  Og 
        La  Ce  Pr  Nd  Pm  Sm  Eu  Gd  Tb  Dy  Ho  Er  Tm  Yb  Lu     
        Ac  Th  Pa  U   Np  Pu  Am  Cm  Bk  Cf  Es  Fm  Md  No  Lr     

We can also interrogate the periodic table structure, for example looking up elements by row and group:

mgc.Element.from_row_and_group(3, 14)
Element Si

Periodic Table

The widget_periodictable is an interactive periodic table widget that allows particular elements to be highlighted and identifiers for selected elements to be retrieved.

As such, the widget could form part of a simple end user application for looking up properties of selected elements, or highlighting elements within the table based on an analysis of a simple compound.

from widget_periodictable import PTableWidget

widget = PTableWidget(states = 3, selected_elements = {"C": 0, "Si": 1, "Ge": 2}, 
                      selected_colors = ['pink', 'yellow', 'lightblue'], 
                      disabled_elements = ['B', 'Al', 'Ga'],
                      unselected_color='white', border_color = 'black', width = '20px')
display(widget)

The periodic table widget can return symbols for selected elements, which means we could use it as an interface element for an automated lookup of various properties of selected items.

We can also use code to control which elements in the table are highlighted, we means we could also highlight elements in the table that may have been identified through some other lookup service. For example, highlight all the elements in the table contained in a particular compound.

mendeleev

The mendeleev package provides “an API for accessing various properties of elements from the periodic table of elements”.

For example, we can retrieve key properties associated with the elements referenced by the chemical symbol:

from mendeleev import Si, Fe, O

print("Si's name: ", Si.name)
print("Fe's atomic number:", Fe.atomic_number)
print("O's atomic weight: ", O.atomic_weight)
Si's name:  Silicon
Fe's atomic number: 26
O's atomic weight:  15.999

We can also reference elements by name and atomic number, as well as symbol:

Note

Note that we seem to get the American spelling of the name!

from mendeleev import element

si, al,o  = [element('Si'), element(13), element('Oxygen') ]
si.name, al.name,o.name, al.oxistates
('Silicon', 'Aluminum', 'Oxygen', [3])

As well as the basic elements, we can also look up isotopes:

for iso in Fe.isotopes:
    print('{0:4d} {1:4d} {2:10.5f} {3:8.2e} {4:6.2f} {5:}'.format(
        iso.atomic_number, iso.mass_number, iso.mass, iso.mass_uncertainty, iso.abundance * 100.0, iso.is_radioactive))
  26   54   53.93961 3.00e-06   5.85 False
  26   56   55.93494 3.00e-06  91.75 False
  26   57   56.93539 3.00e-06   2.12 False
  26   58   57.93327 3.00e-06   0.28 False

In addition to the simple API, the medeleev package also provides a rich interactive periodic table widget.

The widget has a depnedency on the Boken charting package, which must be loaded in and configured first:

from bokeh.plotting import output_notebook, output_file
# Note that the periodic table widget will still render in a Jupyter Book display
output_notebook()

from mendeleev.fetch import fetch_table
from mendeleev.plotting import periodic_plot

ptable = fetch_table('elements')
periodic_plot(ptable)
Loading BokehJS ...

We can also configure the periodic table display, for example, adding colour highlights:

periodic_plot(ptable, colorby='jmol_color', title="JMol Colors", decimals=3, width=700)
#periodic_plot(ptable, colorby='cpk_color', title='CPK Colors')
#periodic_plot(ptable, colorby='molcas_gv_color', title='MOLCAS GV Colors')

If required, custom colour maps can also be applied:

import seaborn as sns
from matplotlib import colors

blockcmap = {b : colors.rgb2hex(c) for b, c in zip(['s', 'p', 'd', 'f'], sns.color_palette('deep'))}
ptable['block_color'] = ptable['block'].map(blockcmap)

periodic_plot(ptable, colorby='block_color',
              width=700)

Elements may also be styled in the table according the value of specific properties:

periodic_plot(ptable, attribute='covalent_radius_pyykko',
              colorby='attribute', title="Covalent Radii of Pyykko",
              width=700)