0
# Constants and Utilities
1
2
Fundamental physical constants, crystallographic calculations, uncertainty parsing, periodic table data visualization tools, and biomolecule support for scientific applications.
3
4
## Capabilities
5
6
### Physical Constants
7
8
Fundamental physical constants used throughout the periodictable package for calculations and unit conversions.
9
10
```python { .api }
11
# From periodictable.constants module
12
avogadro_number: float = 6.02214076e23 # Avogadro's number (mol⁻¹)
13
planck_constant: float = 6.62607015e-34 # Planck constant (J⋅Hz⁻¹)
14
electron_volt: float = 1.602176634e-19 # Electron volt (J/eV)
15
speed_of_light: float = 299792458 # Speed of light (m/s)
16
electron_radius: float = 2.8179403205e-15 # Classical electron radius (m)
17
neutron_mass: float = 1.00866491606 # Neutron mass (u)
18
atomic_mass_constant: float = 1.66053906892e-27 # Atomic mass unit (kg/u)
19
electron_mass: float = 5.485799090441e-4 # Electron mass (u)
20
```
21
22
Usage examples:
23
24
```python
25
from periodictable.constants import *
26
import periodictable as pt
27
28
# Unit conversions
29
print(f"Avogadro's number: {avogadro_number:.6e} mol⁻¹")
30
print(f"eV to Joules: {electron_volt:.6e} J/eV")
31
print(f"Speed of light: {speed_of_light} m/s")
32
33
# Molecular mass calculations
34
water = pt.formula("H2O")
35
mass_grams = water.mass * atomic_mass_constant * 1000 # Convert to grams
36
molecules_per_mole = avogadro_number
37
molar_mass = mass_grams * molecules_per_mole
38
print(f"Water molar mass: {molar_mass:.2f} g/mol")
39
40
# Energy calculations
41
lambda_cu = 1.5418 # Å, Cu K-alpha
42
energy_joules = planck_constant * speed_of_light / (lambda_cu * 1e-10)
43
energy_ev = energy_joules / electron_volt
44
energy_kev = energy_ev / 1000
45
print(f"Cu K-alpha: {lambda_cu} Å = {energy_kev:.3f} keV")
46
47
# Classical electron radius in X-ray calculations
48
print(f"Electron radius: {electron_radius:.6e} m")
49
```
50
51
### Crystallographic Utilities
52
53
Calculate unit cell volumes and properties for crystallographic applications and density estimations.
54
55
```python { .api }
56
def cell_volume(a: float = None, b: float = None, c: float = None,
57
alpha: float = None, beta: float = None,
58
gamma: float = None) -> float:
59
"""
60
Calculate crystallographic unit cell volume.
61
62
Args:
63
a, b, c: Unit cell lengths in Ångström
64
alpha, beta, gamma: Unit cell angles in degrees
65
66
Returns:
67
Unit cell volume in ų (cubic Ångström)
68
69
Note:
70
For cubic: provide a only
71
For tetragonal: provide a, c
72
For orthorhombic: provide a, b, c
73
For hexagonal: provide a, c (gamma=120° assumed)
74
For general case: provide all parameters
75
"""
76
```
77
78
Usage examples:
79
80
```python
81
from periodictable.util import cell_volume
82
import math
83
84
# Cubic crystal (e.g., simple cubic silicon)
85
a_cubic = 5.43 # Å, silicon lattice parameter
86
vol_cubic = cell_volume(a=a_cubic)
87
print(f"Cubic Si unit cell: {vol_cubic:.2f} ų")
88
89
# Face-centered cubic (real silicon structure)
90
a_fcc = 5.43 # Å
91
vol_fcc = cell_volume(a=a_fcc) # Same as cubic for FCC primitive cell
92
atoms_per_unit_cell = 8 # FCC has 8 atoms per conventional cell
93
vol_per_atom = vol_fcc / atoms_per_unit_cell
94
print(f"Si volume per atom: {vol_per_atom:.2f} ų/atom")
95
96
# Hexagonal (e.g., graphite)
97
a_hex = 2.46 # Å
98
c_hex = 6.71 # Å
99
vol_hex = cell_volume(a=a_hex, c=c_hex, gamma=120)
100
print(f"Hexagonal graphite: {vol_hex:.2f} ų")
101
102
# Orthorhombic
103
a_ortho, b_ortho, c_ortho = 4.0, 5.0, 6.0 # Å
104
vol_ortho = cell_volume(a=a_ortho, b=b_ortho, c=c_ortho)
105
print(f"Orthorhombic cell: {vol_ortho:.2f} ų")
106
107
# General triclinic case
108
vol_triclinic = cell_volume(a=5.0, b=6.0, c=7.0,
109
alpha=85, beta=90, gamma=95)
110
print(f"Triclinic cell: {vol_triclinic:.2f} ų")
111
112
# Density calculation from unit cell
113
silicon = pt.formula("Si")
114
atoms_per_cell = 8 # Diamond cubic
115
cell_vol_cm3 = vol_cubic * 1e-24 # Convert ų to cm³
116
mass_per_cell = atoms_per_cell * silicon.mass * 1.66054e-24 # u to g
117
calculated_density = mass_per_cell / cell_vol_cm3
118
print(f"Calculated Si density: {calculated_density:.2f} g/cm³")
119
```
120
121
### Uncertainty Parsing
122
123
Parse scientific notation with uncertainties in parenthetical format commonly used in scientific literature.
124
125
```python { .api }
126
def parse_uncertainty(s: str) -> tuple:
127
"""
128
Parse uncertainty notation like "23.0035(12)" into value and uncertainty.
129
130
Args:
131
s: String with uncertainty notation
132
133
Returns:
134
tuple: (value, uncertainty) as floats
135
136
Examples:
137
"23.0035(12)" -> (23.0035, 0.0012)
138
"1.234(5)" -> (1.234, 0.005)
139
"456.78(123)" -> (456.78, 1.23)
140
"""
141
```
142
143
Usage examples:
144
145
```python
146
from periodictable.util import parse_uncertainty
147
148
# Scientific measurements with uncertainties
149
measurements = [
150
"23.0035(12)", # NIST atomic mass format
151
"1.234(5)", # Standard uncertainty notation
152
"456.78(123)", # Large uncertainty
153
"0.0012345(67)", # Small values
154
"1234567(89)" # Integer-like with uncertainty
155
]
156
157
print("Parsed uncertainties:")
158
for measurement in measurements:
159
value, uncertainty = parse_uncertainty(measurement)
160
print(f"{measurement:12s} -> {value} ± {uncertainty}")
161
162
# Use in atomic mass calculations
163
import periodictable as pt
164
165
# Simulate parsing atomic mass with uncertainty
166
mass_string = "55.845(2)" # Iron atomic mass with uncertainty
167
mass_value, mass_uncertainty = parse_uncertainty(mass_string)
168
169
print(f"\nIron atomic mass: {mass_value} ± {mass_uncertainty} u")
170
print(f"Relative uncertainty: {mass_uncertainty/mass_value:.2e}")
171
172
# Error propagation example
173
iron = pt.Fe
174
print(f"Tabulated Fe mass: {iron.mass} u")
175
print(f"Difference from parsed: {abs(iron.mass - mass_value):.6f} u")
176
```
177
178
### Periodic Table Visualization
179
180
Create visual representations and formatted tables of periodic table data for analysis and presentation.
181
182
```python { .api }
183
def table_plot(data, form: str = "line", label: str = None,
184
title: str = None) -> None:
185
"""
186
Plot periodic table data in various formats.
187
188
Args:
189
data: Dictionary mapping elements to values, or property name string
190
form: Plot type ("line", "bar", "scatter", "table")
191
label: Y-axis label for the data
192
title: Plot title
193
194
Note:
195
Requires matplotlib for plotting functionality
196
"""
197
```
198
199
Usage examples:
200
201
```python
202
from periodictable.plot import table_plot
203
import periodictable as pt
204
205
# Plot atomic masses
206
try:
207
mass_data = {el: el.mass for el in pt.elements if el.mass}
208
table_plot(mass_data, form="line", label="Atomic Mass (u)",
209
title="Atomic Masses vs Atomic Number")
210
211
# Plot densities
212
density_data = {el: el.density for el in pt.elements
213
if el.density and el.number <= 86}
214
table_plot(density_data, form="scatter", label="Density (g/cm³)",
215
title="Element Densities")
216
217
# Plot covalent radii (triggers lazy loading)
218
radii_data = {}
219
for el in pt.elements:
220
if el.number <= 54: # First few periods
221
try:
222
radii_data[el] = el.covalent_radius
223
except (AttributeError, TypeError):
224
pass
225
226
table_plot(radii_data, form="bar", label="Covalent Radius (Å)",
227
title="Covalent Radii")
228
229
except ImportError:
230
print("Matplotlib required for plotting")
231
232
# Create data tables without plotting
233
elements_subset = [pt.H, pt.He, pt.Li, pt.Be, pt.B, pt.C, pt.N, pt.O]
234
print("Light element properties:")
235
print("El Mass Density")
236
for el in elements_subset:
237
density = el.density if el.density else "N/A"
238
print(f"{el.symbol:2s} {el.mass:8.4f} {density}")
239
```
240
241
### Biomolecule Support
242
243
Support for biological molecules including amino acids, nucleic acids, and common biochemical compounds with labile hydrogen tracking.
244
245
```python { .api }
246
# From periodictable.fasta module
247
class Molecule:
248
"""Biomolecule with labile hydrogen support for deuteration studies."""
249
250
def __init__(self, formula: str = None, name: str = None,
251
labile: int = 0, charge: int = 0):
252
"""
253
Args:
254
formula: Chemical formula
255
name: Molecule name
256
labile: Number of labile hydrogens
257
charge: Net charge
258
"""
259
260
class Sequence(Molecule):
261
"""Read amino acid and DNA/RNA sequences from FASTA-like strings."""
262
263
def __init__(self, sequence: str, molecule_type: str = "protein"):
264
"""
265
Args:
266
sequence: FASTA sequence string
267
molecule_type: "protein", "DNA", or "RNA"
268
"""
269
270
# Standard biochemical data
271
AMINO_ACID_CODES: dict # 20 standard amino acids by single letter
272
RNA_CODES: dict # RNA nucleotides (A, U, G, C)
273
DNA_CODES: dict # DNA nucleotides (A, T, G, C)
274
RNA_BASES: dict # Individual RNA bases
275
DNA_BASES: dict # Individual DNA bases
276
NUCLEIC_ACID_COMPONENTS: dict # Nucleic acid molecular components
277
LIPIDS: dict # Common lipid molecules
278
CARBOHYDRATE_RESIDUES: dict # Sugar and carbohydrate units
279
280
# Reference SLD values
281
H2O_SLD: float = -0.5603 # H2O neutron SLD at 20°C (10⁻⁶ Ų⁻²)
282
D2O_SLD: float = 6.3350 # D2O neutron SLD at 20°C (10⁻⁶ Ų⁻²)
283
```
284
285
Usage examples:
286
287
```python
288
from periodictable.fasta import *
289
import periodictable as pt
290
291
# Amino acids
292
print("Standard amino acids:")
293
for code, amino_acid in list(AMINO_ACID_CODES.items())[:5]:
294
print(f"{code}: {amino_acid.name} - {amino_acid.formula}")
295
296
# Create peptide sequence
297
peptide_seq = "MVLSPADKTNVKAAW" # Sample sequence
298
protein = Sequence(peptide_seq, molecule_type="protein")
299
print(f"\nPeptide formula: {protein.formula}")
300
print(f"Molecular mass: {protein.mass:.2f} u")
301
302
# DNA sequence
303
dna_seq = "ATCGATCGATCG"
304
dna = Sequence(dna_seq, molecule_type="DNA")
305
print(f"DNA formula: {dna.formula}")
306
307
# Labile hydrogen tracking for deuteration
308
# Water molecules
309
h2o = Molecule("H2O", labile=2) # Both H are labile
310
print(f"H2O labile H: {h2o.labile}")
311
312
# Reference SLD values for contrast calculations
313
print(f"\nSolvent SLD values:")
314
print(f"H2O: {H2O_SLD:.4f} × 10⁻⁶ Ų⁻²")
315
print(f"D2O: {D2O_SLD:.4f} × 10⁻⁶ Ų⁻²")
316
print(f"Contrast: {D2O_SLD - H2O_SLD:.4f} × 10⁻⁶ Ų⁻²")
317
318
# Lipids and carbohydrates
319
print("\nBiochemical molecules:")
320
for name, molecule in list(LIPIDS.items())[:3]:
321
print(f"{name}: {molecule.formula}")
322
323
for name, molecule in list(CARBOHYDRATE_RESIDUES.items())[:3]:
324
print(f"{name}: {molecule.formula}")
325
```
326
327
### Activation Analysis Support
328
329
Support for neutron activation analysis calculations including sample preparation and flux environment modeling.
330
331
```python { .api }
332
# From periodictable.activation module
333
class Sample:
334
"""Neutron activation sample with composition and irradiation history."""
335
336
def __init__(self, formula, mass: float = None, name: str = None):
337
"""
338
Args:
339
formula: Sample chemical formula
340
mass: Sample mass in grams
341
name: Sample identifier
342
"""
343
344
class ActivationEnvironment:
345
"""Neutron flux environment for activation calculations."""
346
347
def __init__(self, flux: float, energy: str = "thermal"):
348
"""
349
Args:
350
flux: Neutron flux in n/cm²/s
351
energy: Neutron energy spectrum ("thermal", "epithermal", "fast")
352
"""
353
354
class ActivationResult:
355
"""Results from neutron activation calculations."""
356
357
@property
358
def activity(self) -> dict:
359
"""Activities by isotope in Bq."""
360
361
@property
362
def dose_rate(self) -> float:
363
"""Dose rate in μSv/hr at 1m."""
364
```
365
366
Usage examples:
367
368
```python
369
from periodictable.activation import *
370
import periodictable as pt
371
372
# Create sample for activation analysis
373
steel_sample = Sample("Fe + 0.8%C + 2%Mn", mass=10.0, name="Steel sample")
374
aluminum_sample = Sample("Al", mass=5.0, name="Al foil")
375
376
# Define neutron environment
377
reactor_flux = ActivationEnvironment(flux=1e13, energy="thermal") # n/cm²/s
378
print(f"Reactor thermal flux: {reactor_flux.flux:.0e} n/cm²/s")
379
380
# Calculate activation (conceptual - requires specific implementation)
381
print(f"Steel sample: {steel_sample.formula}")
382
print(f"Sample mass: {steel_sample.mass} g")
383
print(f"Environment: {reactor_flux.energy} neutrons")
384
```
385
386
### Core Utility Functions
387
388
Essential utility functions for working with periodic table objects, managing custom tables, and type checking atomic objects.
389
390
```python { .api }
391
# Table management functions
392
def default_table(table=None) -> PeriodicTable:
393
"""Return the default periodic table unless a specific table is requested."""
394
395
def change_table(atom, table) -> Union[Element, Isotope, Ion]:
396
"""Get the same element, isotope, or ion from a different periodic table."""
397
398
# Type checking functions
399
def isatom(val) -> bool:
400
"""Test if value is any atomic object (element, isotope, or ion)."""
401
402
def iselement(val) -> bool:
403
"""Test if value is an element (not isotope or ion)."""
404
405
def isisotope(val) -> bool:
406
"""Test if value is an isotope."""
407
408
def ision(val) -> bool:
409
"""Test if value is an ion."""
410
```
411
412
Usage examples:
413
414
```python
415
import periodictable as pt
416
from periodictable.core import (default_table, change_table,
417
isatom, iselement, isisotope, ision)
418
419
# Table management
420
default = default_table() # Get the standard table
421
print(f"Default table contains {len(list(default))} elements")
422
423
# Custom table workflow (conceptual)
424
# custom_table = create_custom_table() # User-defined table
425
iron_default = pt.Fe
426
# iron_custom = change_table(iron_default, custom_table)
427
428
# Type checking for safe operations
429
iron = pt.Fe
430
iron56 = pt.Fe[56]
431
iron2_ion = pt.Fe.ion[2]
432
433
print(f"Iron is atom: {isatom(iron)}") # True
434
print(f"Iron is element: {iselement(iron)}") # True
435
print(f"Iron-56 is isotope: {isisotope(iron56)}") # True
436
print(f"Fe²⁺ is ion: {ision(iron2_ion)}") # True
437
438
# Safe property access patterns
439
def get_mass_info(atom_obj):
440
"""Safely extract mass information from any atomic object."""
441
if isatom(atom_obj):
442
mass = atom_obj.mass
443
if isisotope(atom_obj):
444
return f"Isotope {atom_obj.symbol}-{atom_obj.isotope}: {mass:.4f} u"
445
elif ision(atom_obj):
446
charge_sign = "+" if atom_obj.charge > 0 else ""
447
return f"Ion {atom_obj.symbol}{charge_sign}{atom_obj.charge}: {mass:.4f} u"
448
else:
449
return f"Element {atom_obj.symbol}: {mass:.4f} u"
450
else:
451
return "Not an atomic object"
452
453
# Test type checking
454
for obj in [iron, iron56, iron2_ion, "not_atom"]:
455
print(get_mass_info(obj))
456
```
457
458
## Types
459
460
```python { .api }
461
# Constants (all float values)
462
avogadro_number: float
463
planck_constant: float
464
electron_volt: float
465
speed_of_light: float
466
electron_radius: float
467
neutron_mass: float
468
atomic_mass_constant: float
469
electron_mass: float
470
471
# Biomolecule data (all dict mappings)
472
AMINO_ACID_CODES: dict
473
RNA_CODES: dict
474
DNA_CODES: dict
475
RNA_BASES: dict
476
DNA_BASES: dict
477
NUCLEIC_ACID_COMPONENTS: dict
478
LIPIDS: dict
479
CARBOHYDRATE_RESIDUES: dict
480
481
# Reference values
482
H2O_SLD: float
483
D2O_SLD: float
484
485
class Molecule:
486
"""Biomolecule with labile hydrogen tracking."""
487
formula: str
488
name: str
489
labile: int
490
charge: int
491
mass: float
492
493
class Sequence(Molecule):
494
"""Biological sequence (protein, DNA, RNA)."""
495
def __init__(self, sequence: str, molecule_type: str = "protein"): ...
496
497
class Sample:
498
"""Activation analysis sample."""
499
formula: str
500
mass: float
501
name: str
502
503
class ActivationEnvironment:
504
"""Neutron flux environment."""
505
flux: float
506
energy: str
507
508
class ActivationResult:
509
"""Activation calculation results."""
510
@property
511
def activity(self) -> dict: ...
512
@property
513
def dose_rate(self) -> float: ...
514
```