0
# Chemical Formulas
1
2
Parse chemical formulas, calculate molecular properties, create mixtures by weight or volume, and perform isotope substitutions with full support for composite material calculations and property estimation.
3
4
## Capabilities
5
6
### Formula Parsing
7
8
Parse chemical formula strings into Formula objects with automatic composition analysis and property calculation capabilities.
9
10
```python { .api }
11
def formula(compound: str = None, density: float = None,
12
natural_density: float = None, name: str = None,
13
table: PeriodicTable = None) -> Formula:
14
"""
15
Parse chemical formula string into Formula object.
16
17
Args:
18
compound: Chemical formula string (e.g., 'H2O', 'CaCO3', 'C6H12O6')
19
density: Known density in g/cm³
20
natural_density: Density with natural isotope abundances
21
name: Descriptive name for the compound
22
table: Custom periodic table to use for parsing
23
24
Returns:
25
Formula object with composition and properties
26
"""
27
```
28
29
Usage examples:
30
31
```python
32
import periodictable as pt
33
34
# Simple molecules
35
water = pt.formula("H2O")
36
methane = pt.formula("CH4")
37
glucose = pt.formula("C6H12O6")
38
39
# Complex formulas with parentheses
40
calcium_phosphate = pt.formula("Ca3(PO4)2")
41
hydrated_salt = pt.formula("CuSO4·5H2O", name="Copper sulfate pentahydrate")
42
43
# With known density
44
quartz = pt.formula("SiO2", density=2.65, name="Quartz")
45
46
# Isotope-specific formulas
47
heavy_water = pt.formula("D2O", name="Heavy water")
48
carbon13_methane = pt.formula("13CH4")
49
50
# Formula with charges
51
sodium_chloride = pt.formula("NaCl") # Neutral overall
52
```
53
54
### Mixture Creation by Weight
55
56
Create homogeneous mixtures by specifying weight percentages of different materials with automatic density and property calculations.
57
58
```python { .api }
59
def mix_by_weight(*args, density: float = None,
60
natural_density: float = None, name: str = None,
61
table: PeriodicTable = None) -> Formula:
62
"""
63
Create mixture apportioned by weight percentages.
64
65
Args:
66
*args: Alternating formula/weight pairs (formula1, weight1, formula2, weight2, ...)
67
density: Known density of mixture
68
natural_density: Density with natural abundances
69
name: Descriptive name for mixture
70
table: Custom periodic table
71
72
Returns:
73
Formula representing the mixture
74
"""
75
```
76
77
Usage examples:
78
79
```python
80
import periodictable as pt
81
82
# Simple mixture: 80% H2O, 20% D2O by weight
83
water_mixture = pt.mix_by_weight("H2O", 80, "D2O", 20, name="Mixed water")
84
85
# Complex mixture
86
steel_alloy = pt.mix_by_weight(
87
"Fe", 95.0, # 95% iron
88
"C", 0.8, # 0.8% carbon
89
"Mn", 2.0, # 2% manganese
90
"Si", 1.2, # 1.2% silicon
91
"Cr", 1.0, # 1% chromium
92
density=7.85,
93
name="Carbon steel"
94
)
95
96
# Using Formula objects
97
concrete_mix = pt.mix_by_weight(
98
pt.formula("Ca(OH)2"), 15, # Lime
99
pt.formula("SiO2"), 60, # Silica
100
pt.formula("Al2O3"), 25, # Alumina
101
name="Concrete mixture"
102
)
103
104
print(f"Steel composition: {steel_alloy.atoms}")
105
print(f"Steel density: {steel_alloy.density} g/cm³")
106
```
107
108
### Mixture Creation by Volume
109
110
Create homogeneous mixtures by specifying volume percentages with density calculations based on component volumes.
111
112
```python { .api }
113
def mix_by_volume(*args, density: float = None,
114
natural_density: float = None, name: str = None,
115
table: PeriodicTable = None) -> Formula:
116
"""
117
Create mixture apportioned by volume percentages.
118
119
Args:
120
*args: Alternating formula/volume pairs (formula1, vol1, formula2, vol2, ...)
121
density: Known density of mixture
122
natural_density: Density with natural abundances
123
name: Descriptive name for mixture
124
table: Custom periodic table
125
126
Returns:
127
Formula representing the mixture
128
"""
129
```
130
131
Usage examples:
132
133
```python
134
import periodictable as pt
135
136
# Air composition by volume
137
air = pt.mix_by_volume(
138
"N2", 78.08, # Nitrogen
139
"O2", 20.95, # Oxygen
140
"Ar", 0.93, # Argon
141
"CO2", 0.04, # Carbon dioxide
142
name="Air at STP"
143
)
144
145
# Liquid mixture
146
ethanol_water = pt.mix_by_volume(
147
pt.formula("C2H5OH", density=0.789), 40, # 40% ethanol by volume
148
pt.formula("H2O", density=1.0), 60, # 60% water by volume
149
name="40% ethanol solution"
150
)
151
152
print(f"Air molecular composition: {air.hill}")
153
print(f"Ethanol solution density: {ethanol_water.density:.3f} g/cm³")
154
```
155
156
### Formula Properties and Calculations
157
158
Access comprehensive molecular properties including mass, charge, composition analysis, and derived quantities.
159
160
```python { .api }
161
class Formula:
162
"""Chemical formula with composition and property calculations."""
163
164
# Core composition
165
atoms: dict # Dictionary mapping atoms to counts
166
mass: float # Molecular mass in atomic mass units (u)
167
molecular_mass: float # Molecular mass in grams
168
169
# Physical properties
170
density: float # Mass density in g/cm³
171
natural_density: float # Density with natural isotopes
172
173
# Chemical properties
174
charge: int # Net electrical charge
175
hill: str # Formula in Hill notation (C, H, others alphabetical)
176
177
# Composition analysis
178
mass_fraction: dict # Fractional mass of each component
179
180
def natural_mass_ratio(self) -> float:
181
"""Ratio of natural to isotope-substituted mass."""
182
```
183
184
Usage examples:
185
186
```python
187
import periodictable as pt
188
189
# Create and analyze glucose
190
glucose = pt.formula("C6H12O6", density=1.54)
191
192
# Basic properties
193
print(f"Molecular formula: {glucose.hill}") # C6H12O6
194
print(f"Molecular mass: {glucose.mass:.2f} u") # 180.16 u
195
print(f"Mass in grams: {glucose.molecular_mass:.2e} g") # 2.99e-22 g
196
print(f"Density: {glucose.density} g/cm³") # 1.54
197
198
# Composition analysis
199
print("Mass fractions:")
200
for atom, fraction in glucose.mass_fraction.items():
201
print(f" {atom.symbol}: {fraction:.3f}")
202
203
# Atomic composition
204
print("Atomic composition:")
205
for atom, count in glucose.atoms.items():
206
print(f" {atom.symbol}: {count}")
207
208
# For charged species
209
salt = pt.formula("Na+Cl-") # Conceptual - parser handles neutral compounds
210
print(f"Net charge: {salt.charge}") # 0 (neutral overall)
211
```
212
213
### Isotope Substitution
214
215
Replace specific elements with isotopes to study isotope effects on properties and scattering characteristics.
216
217
```python { .api }
218
def replace(self, source, target, portion: float = 1) -> 'Formula':
219
"""
220
Create new formula with isotope substitution.
221
222
Args:
223
source: Element to replace (Element, Isotope, or Ion)
224
target: Replacement isotope/element
225
portion: Fraction to replace (0-1, default 1 for complete)
226
227
Returns:
228
New Formula with substitution applied
229
"""
230
```
231
232
Usage examples:
233
234
```python
235
import periodictable as pt
236
237
# Deuteration of water
238
water = pt.formula("H2O")
239
heavy_water = water.replace(pt.H, pt.D) # Replace all H with D
240
print(f"H2O mass: {water.mass:.3f} u") # ~18.015 u
241
print(f"D2O mass: {heavy_water.mass:.3f} u") # ~20.028 u
242
243
# Partial deuteration (50%)
244
partial_d2o = water.replace(pt.H, pt.D, portion=0.5)
245
print(f"50% deuterated mass: {partial_d2o.mass:.3f} u")
246
247
# Carbon-13 labeling in glucose
248
glucose = pt.formula("C6H12O6")
249
c13_glucose = glucose.replace(pt.C, pt.C[13]) # All carbon to C-13
250
print(f"Natural glucose: {glucose.mass:.3f} u")
251
print(f"C-13 glucose: {c13_glucose.mass:.3f} u")
252
253
# Partial labeling
254
glucose_1c13 = glucose.replace(pt.C, pt.C[13], portion=1/6) # One C-13
255
print(f"One C-13 glucose: {glucose_1c13.mass:.3f} u")
256
```
257
258
### Volume and Density Estimation
259
260
Estimate molecular volumes and densities using crystallographic data and packing factors for materials without known densities.
261
262
```python { .api }
263
def volume(self, packing_factor: str = None, **kwargs) -> float:
264
"""
265
Estimate unit cell volume using atomic radii and packing factors.
266
267
Args:
268
packing_factor: Crystal structure ('cubic', 'fcc', 'bcc', 'hcp', 'diamond')
269
**kwargs: Additional crystallographic parameters
270
271
Returns:
272
Estimated volume in Ų
273
"""
274
```
275
276
Available packing factors and their values:
277
278
```python { .api }
279
PACKING_FACTORS = {
280
'cubic': π/6, # Simple cubic (52.4%)
281
'bcc': π*√3/8, # Body-centered cubic (68.0%)
282
'fcc': π/√18, # Face-centered cubic (74.0%)
283
'hcp': π/√18, # Hexagonal close-packed (74.0%)
284
'diamond': π*√3/16 # Diamond structure (34.0%)
285
}
286
```
287
288
Usage examples:
289
290
```python
291
import periodictable as pt
292
293
# Estimate volume for different crystal structures
294
silicon = pt.formula("Si")
295
296
# Different packing assumptions
297
vol_diamond = silicon.volume(packing_factor='diamond') # Diamond structure
298
vol_fcc = silicon.volume(packing_factor='fcc') # FCC assumption
299
300
print(f"Si diamond structure volume: {vol_diamond:.2f} Ų")
301
print(f"Si FCC structure volume: {vol_fcc:.2f} Ų")
302
303
# For compounds - estimates based on component radii
304
nacl = pt.formula("NaCl")
305
nacl_volume = nacl.volume(packing_factor='cubic')
306
print(f"NaCl estimated volume: {nacl_volume:.2f} Ų")
307
308
# Compare with known density
309
quartz = pt.formula("SiO2", density=2.65)
310
estimated_vol = quartz.volume()
311
actual_vol = quartz.mass / (quartz.density * 6.022e23) * 1e24 # Convert to Ų
312
print(f"SiO2 estimated volume: {estimated_vol:.2f} Ų")
313
print(f"SiO2 actual volume: {actual_vol:.2f} Ų")
314
```
315
316
### Table Management
317
318
Switch formulas between different periodic tables and access custom element data for specialized calculations.
319
320
```python { .api }
321
def change_table(self, table: PeriodicTable) -> 'Formula':
322
"""
323
Create equivalent formula using different periodic table.
324
325
Args:
326
table: Target periodic table with custom data
327
328
Returns:
329
New Formula using the specified table
330
"""
331
```
332
333
Usage examples:
334
335
```python
336
import periodictable as pt
337
from periodictable.core import PeriodicTable
338
339
# Create custom table with modified properties
340
custom_table = PeriodicTable()
341
# ... customize table properties ...
342
343
# Convert formula to use custom table
344
water = pt.formula("H2O")
345
custom_water = water.change_table(custom_table)
346
347
print(f"Original table: {water.atoms[pt.H].mass}")
348
print(f"Custom table: {custom_water.atoms[custom_table.H].mass}")
349
```
350
351
### Utility Functions
352
353
Additional functions for formula parsing, composition analysis, and formatting for different output formats.
354
355
```python { .api }
356
def count_elements(compound, by_isotope: bool = False) -> dict:
357
"""
358
Count elements in a compound without creating Formula object.
359
360
Args:
361
compound: Formula string or Formula object
362
by_isotope: Count isotopes separately if True
363
364
Returns:
365
Dictionary of element/isotope counts
366
"""
367
368
def pretty(compound, mode: str = 'unicode') -> str:
369
"""
370
Format chemical formula with subscripts and superscripts.
371
372
Args:
373
compound: Formula string or Formula object
374
mode: Output format ('unicode', 'html', 'latex')
375
376
Returns:
377
Formatted formula string
378
"""
379
380
def parse_formula(formula_str: str, table: PeriodicTable = None) -> list:
381
"""
382
Parse formula string into list of (element, count) tuples.
383
384
Args:
385
formula_str: Chemical formula string
386
table: Periodic table to use for parsing
387
388
Returns:
389
List of (atom, count) tuples
390
"""
391
```
392
393
Usage examples:
394
395
```python
396
import periodictable as pt
397
from periodictable.formulas import count_elements, pretty, parse_formula
398
399
# Count elements
400
glucose_counts = count_elements("C6H12O6")
401
print(glucose_counts) # {'C': 6, 'H': 12, 'O': 6}
402
403
# Format with subscripts
404
water_pretty = pretty("H2O")
405
print(water_pretty) # H₂O (with Unicode subscripts)
406
407
caffeine_pretty = pretty("C8H10N4O2", mode='html')
408
print(caffeine_pretty) # C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>
409
410
# Parse formula structure
411
parsed = parse_formula("Ca(OH)2")
412
print(parsed) # [(Ca, 1), (O, 2), (H, 2)]
413
```
414
415
## Types
416
417
```python { .api }
418
class Formula:
419
"""Chemical formula with composition and property calculations."""
420
atoms: dict
421
mass: float
422
molecular_mass: float
423
density: float
424
natural_density: float
425
charge: int
426
hill: str
427
mass_fraction: dict
428
def replace(self, source, target, portion: float = 1) -> 'Formula': ...
429
def volume(self, packing_factor: str = None, **kwargs) -> float: ...
430
def change_table(self, table: PeriodicTable) -> 'Formula': ...
431
def natural_mass_ratio(self) -> float: ...
432
def neutron_sld(self, wavelength: float = None, energy: float = None) -> tuple: ...
433
def xray_sld(self, energy: float = None, wavelength: float = None) -> tuple: ...
434
435
PACKING_FACTORS: dict = {
436
'cubic': float,
437
'bcc': float,
438
'fcc': float,
439
'hcp': float,
440
'diamond': float
441
}
442
```