pyEQL 0.5.2__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyEQL/__init__.py +50 -43
- pyEQL/activity_correction.py +481 -707
- pyEQL/database/geothermal.dat +5693 -0
- pyEQL/database/llnl.dat +19305 -0
- pyEQL/database/phreeqc_license.txt +54 -0
- pyEQL/database/pyeql_db.json +35902 -0
- pyEQL/engines.py +793 -0
- pyEQL/equilibrium.py +148 -228
- pyEQL/functions.py +121 -416
- pyEQL/pint_custom_units.txt +2 -2
- pyEQL/presets/Ringers lactate.yaml +20 -0
- pyEQL/presets/normal saline.yaml +17 -0
- pyEQL/presets/rainwater.yaml +17 -0
- pyEQL/presets/seawater.yaml +29 -0
- pyEQL/presets/urine.yaml +26 -0
- pyEQL/presets/wastewater.yaml +21 -0
- pyEQL/salt_ion_match.py +53 -284
- pyEQL/solute.py +126 -191
- pyEQL/solution.py +2163 -2090
- pyEQL/utils.py +211 -0
- pyEQL-1.0.3.dist-info/AUTHORS.md +13 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.0.3.dist-info}/COPYING +1 -1
- pyEQL-0.5.2.dist-info/LICENSE → pyEQL-1.0.3.dist-info/LICENSE.txt +3 -7
- pyEQL-1.0.3.dist-info/METADATA +131 -0
- pyEQL-1.0.3.dist-info/RECORD +27 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.0.3.dist-info}/WHEEL +1 -1
- pyEQL/chemical_formula.py +0 -1006
- pyEQL/database/Erying_viscosity.tsv +0 -18
- pyEQL/database/Jones_Dole_B.tsv +0 -32
- pyEQL/database/Jones_Dole_B_inorganic_Jenkins.tsv +0 -75
- pyEQL/database/LICENSE +0 -4
- pyEQL/database/dielectric_parameter.tsv +0 -30
- pyEQL/database/diffusion_coefficient.tsv +0 -116
- pyEQL/database/hydrated_radius.tsv +0 -35
- pyEQL/database/ionic_radius.tsv +0 -35
- pyEQL/database/partial_molar_volume.tsv +0 -22
- pyEQL/database/pitzer_activity.tsv +0 -169
- pyEQL/database/pitzer_volume.tsv +0 -132
- pyEQL/database/template.tsv +0 -14
- pyEQL/database.py +0 -300
- pyEQL/elements.py +0 -4552
- pyEQL/logging_system.py +0 -53
- pyEQL/parameter.py +0 -435
- pyEQL/tests/__init__.py +0 -32
- pyEQL/tests/test_activity.py +0 -578
- pyEQL/tests/test_bulk_properties.py +0 -86
- pyEQL/tests/test_chemical_formula.py +0 -279
- pyEQL/tests/test_debye_length.py +0 -79
- pyEQL/tests/test_density.py +0 -106
- pyEQL/tests/test_dielectric.py +0 -153
- pyEQL/tests/test_effective_pitzer.py +0 -276
- pyEQL/tests/test_mixed_electrolyte_activity.py +0 -154
- pyEQL/tests/test_osmotic_coeff.py +0 -99
- pyEQL/tests/test_pyeql_volume_concentration.py +0 -428
- pyEQL/tests/test_salt_matching.py +0 -337
- pyEQL/tests/test_solute_properties.py +0 -251
- pyEQL/water_properties.py +0 -352
- pyEQL-0.5.2.dist-info/AUTHORS +0 -7
- pyEQL-0.5.2.dist-info/METADATA +0 -72
- pyEQL-0.5.2.dist-info/RECORD +0 -47
- pyEQL-0.5.2.dist-info/entry_points.txt +0 -3
- {pyEQL-0.5.2.dist-info → pyEQL-1.0.3.dist-info}/top_level.txt +0 -0
pyEQL/chemical_formula.py
DELETED
|
@@ -1,1006 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
This module contains classes, functions, and methods to facilitate the
|
|
4
|
-
input, output, and parsing of chemical formulas for pyEQL.
|
|
5
|
-
|
|
6
|
-
The correct case must be used when specifying elements.
|
|
7
|
-
|
|
8
|
-
:copyright: 2013-2020 by Ryan S. Kingsbury
|
|
9
|
-
:license: LGPL, see LICENSE for more details.
|
|
10
|
-
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
# logging system
|
|
14
|
-
import logging
|
|
15
|
-
|
|
16
|
-
# add a filter to emit only unique log messages to the handler
|
|
17
|
-
from pyEQL.logging_system import Unique
|
|
18
|
-
|
|
19
|
-
logger = logging.getLogger(__name__)
|
|
20
|
-
unique = Unique()
|
|
21
|
-
logger.addFilter(unique)
|
|
22
|
-
|
|
23
|
-
# add a handler for console output, since pyEQL is meant to be used interactively
|
|
24
|
-
ch = logging.StreamHandler()
|
|
25
|
-
|
|
26
|
-
# create formatter for the log
|
|
27
|
-
formatter = logging.Formatter("(%(name)s) - %(levelname)s - %(message)s")
|
|
28
|
-
|
|
29
|
-
# add formatter to the handler
|
|
30
|
-
ch.setFormatter(formatter)
|
|
31
|
-
logger.addHandler(ch)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# Formula validation and processing functions. These internal routines
|
|
35
|
-
# parse chemical formulas into a format that can be easily processed
|
|
36
|
-
# by user-facing functions.
|
|
37
|
-
def _invalid_formula(reason):
|
|
38
|
-
raise ValueError("Invalid chemical formula specified - %s" % reason)
|
|
39
|
-
return None
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _check_formula(formula):
|
|
43
|
-
"""
|
|
44
|
-
Parse a chemical formula into a list that separates atomic symbols,
|
|
45
|
-
numbers, and parentheses, and check the formula for compliance with
|
|
46
|
-
formatting rules.
|
|
47
|
-
|
|
48
|
-
Similar to Python's default list() function for strings.
|
|
49
|
-
|
|
50
|
-
Parameters
|
|
51
|
-
----------
|
|
52
|
-
formula: str
|
|
53
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
54
|
-
Valid molecular formulas must meet the following criteria:
|
|
55
|
-
|
|
56
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
57
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
58
|
-
'+', or '-'
|
|
59
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
60
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
61
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
62
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
63
|
-
#. Open parentheses must precede closed parentheses
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Examples
|
|
67
|
-
--------
|
|
68
|
-
>>> _check_formula('Fe2(SO4)3')
|
|
69
|
-
['Fe', '2', '(', 'S', 'O', '4', ')', '3']
|
|
70
|
-
>>> _check_formula('C10H12')
|
|
71
|
-
['C', '10', 'H', '12']
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
# check that formula starts with a letter or open parenthesis
|
|
75
|
-
if not (formula[0].isalpha() or formula[0] == "("):
|
|
76
|
-
_invalid_formula("formula must begin with an element or open parenthesis")
|
|
77
|
-
|
|
78
|
-
# check for mismatched charges
|
|
79
|
-
if "+" in formula and "-" in formula:
|
|
80
|
-
_invalid_formula("ionic formulas cannot contain mismatched charge symbols")
|
|
81
|
-
|
|
82
|
-
# check that ionic formulas end with either a number of a charge symbol
|
|
83
|
-
if "+" in formula:
|
|
84
|
-
if formula.count("+") == 1 and not (
|
|
85
|
-
formula[-1] == "+" or formula[-1].isnumeric()
|
|
86
|
-
):
|
|
87
|
-
_invalid_formula(
|
|
88
|
-
"ionic formulas must end with one or more charge symbols or a single charge symbol and a number"
|
|
89
|
-
)
|
|
90
|
-
elif formula.count("+") > 1:
|
|
91
|
-
start = formula.find("+")
|
|
92
|
-
for char in formula[start:]:
|
|
93
|
-
if char != "+":
|
|
94
|
-
_invalid_formula(
|
|
95
|
-
"ionic formulas must end with one or more charge symbols or a single charge symbol and a number"
|
|
96
|
-
)
|
|
97
|
-
elif "-" in formula:
|
|
98
|
-
if formula.count("-") == 1 and not (
|
|
99
|
-
formula[-1] == "-" or formula[-1].isnumeric()
|
|
100
|
-
):
|
|
101
|
-
_invalid_formula(
|
|
102
|
-
"ionic formulas must end with one or more charge symbols or a single charge symbol and a number"
|
|
103
|
-
)
|
|
104
|
-
elif formula.count("-") > 1:
|
|
105
|
-
start = formula.find("-")
|
|
106
|
-
for char in formula[start:]:
|
|
107
|
-
if char != "-":
|
|
108
|
-
_invalid_formula(
|
|
109
|
-
"ionic formulas must end with one or more charge symbols or a single charge symbol and a number"
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
# check for equal parentheses
|
|
113
|
-
if formula.count("(") != formula.count(")"):
|
|
114
|
-
_invalid_formula("parentheses mismatch")
|
|
115
|
-
|
|
116
|
-
# make sure open parenthesis doesn't end the formula
|
|
117
|
-
if formula.endswith("("):
|
|
118
|
-
_invalid_formula("formula cannot end with open parenthesis")
|
|
119
|
-
|
|
120
|
-
# split the formula string into a list of characters
|
|
121
|
-
input_list = list(formula)
|
|
122
|
-
|
|
123
|
-
for i in range(len(input_list)):
|
|
124
|
-
try:
|
|
125
|
-
# check for invalid characters
|
|
126
|
-
parentheses = ["(", ")"]
|
|
127
|
-
charge_symbols = ["+", "-"]
|
|
128
|
-
|
|
129
|
-
if not (
|
|
130
|
-
input_list[i].isalnum()
|
|
131
|
-
or input_list[i] in parentheses
|
|
132
|
-
or input_list[i] in charge_symbols
|
|
133
|
-
):
|
|
134
|
-
_invalid_formula("contains invalid character")
|
|
135
|
-
|
|
136
|
-
elif input_list[i] == "(":
|
|
137
|
-
# check that open parentheses are followed by an atomic symbol
|
|
138
|
-
if not input_list[i + 1].isalpha():
|
|
139
|
-
_invalid_formula("parentheses must contain elements")
|
|
140
|
-
# make sure that the open parenthesis precedes the nearest closed
|
|
141
|
-
# parenthesis
|
|
142
|
-
try:
|
|
143
|
-
if not i < input_list.index(")", i):
|
|
144
|
-
_invalid_formula(
|
|
145
|
-
"open parenthesis must precede closed parenthesis"
|
|
146
|
-
)
|
|
147
|
-
# add exception for ValueError, in case there is no closed parenthesis
|
|
148
|
-
# after index i
|
|
149
|
-
except ValueError:
|
|
150
|
-
_invalid_formula("open parenthesis must precede closed parenthesis")
|
|
151
|
-
|
|
152
|
-
# removed this rule to allow for organic structural formulas
|
|
153
|
-
# check that closed parenthesis are followed by a number
|
|
154
|
-
# elif input_list[i] == ')':
|
|
155
|
-
# try:
|
|
156
|
-
# if not input_list[i+1].isnumeric():
|
|
157
|
-
# _invalid_formula('parnetheses must be followed by numbers')
|
|
158
|
-
# except IndexError:
|
|
159
|
-
# _invalid_formula('parentheses must be followed by numbers')
|
|
160
|
-
|
|
161
|
-
# concatenate any uppercase letters with up to two subsequent lowercase letters
|
|
162
|
-
elif input_list[i].isupper():
|
|
163
|
-
try:
|
|
164
|
-
if input_list[i + 1].islower():
|
|
165
|
-
try:
|
|
166
|
-
if input_list[i + 2].islower():
|
|
167
|
-
char = input_list.pop(i + 2)
|
|
168
|
-
input_list[i + 1] += char
|
|
169
|
-
except IndexError:
|
|
170
|
-
pass
|
|
171
|
-
char = input_list.pop(i + 1)
|
|
172
|
-
input_list[i] += char
|
|
173
|
-
except IndexError:
|
|
174
|
-
pass
|
|
175
|
-
|
|
176
|
-
# concatenate any adjacent numbers together
|
|
177
|
-
elif input_list[i].isnumeric():
|
|
178
|
-
try:
|
|
179
|
-
j = i + 1
|
|
180
|
-
while input_list[j].isnumeric():
|
|
181
|
-
char = input_list.pop(j)
|
|
182
|
-
input_list[i] += char
|
|
183
|
-
except IndexError:
|
|
184
|
-
pass
|
|
185
|
-
|
|
186
|
-
# concatenate adjacent + or -
|
|
187
|
-
elif input_list[i] == "+" or input_list[i] == "-":
|
|
188
|
-
try:
|
|
189
|
-
if input_list[i + 1] == "+" or input_list[i + 1] == "-":
|
|
190
|
-
j = i + 1
|
|
191
|
-
while input_list[j] == "+" or input_list[j] == "-":
|
|
192
|
-
char = input_list.pop(j)
|
|
193
|
-
input_list[i] += char
|
|
194
|
-
except IndexError:
|
|
195
|
-
pass
|
|
196
|
-
|
|
197
|
-
else:
|
|
198
|
-
pass
|
|
199
|
-
|
|
200
|
-
except IndexError:
|
|
201
|
-
pass
|
|
202
|
-
|
|
203
|
-
# check that all elements are valid
|
|
204
|
-
for item in input_list:
|
|
205
|
-
if item.isalpha():
|
|
206
|
-
if not is_valid_element(item):
|
|
207
|
-
_invalid_formula("invalid element symbol")
|
|
208
|
-
|
|
209
|
-
return input_list
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def _remove_parentheses(formula):
|
|
213
|
-
"""
|
|
214
|
-
Remove parentheses from a formula and distribute the associated numbers
|
|
215
|
-
as appropriate.
|
|
216
|
-
|
|
217
|
-
NOTE: does not support nested parentheses as these violate
|
|
218
|
-
the formatting rules for chemical formulas
|
|
219
|
-
|
|
220
|
-
>>> _remove_parentheses('(Fe2)(SO4)3')
|
|
221
|
-
['Fe', '2', 'S', '3', 'O', '12']
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
See Also
|
|
225
|
-
--------
|
|
226
|
-
_check_formula
|
|
227
|
-
"""
|
|
228
|
-
|
|
229
|
-
# perform validity check and return a list of the chemical formula's components
|
|
230
|
-
input_list = _check_formula(formula)
|
|
231
|
-
output_list = []
|
|
232
|
-
|
|
233
|
-
# remove all parentheses from the formula and distribute numbers accordingly
|
|
234
|
-
i = 0
|
|
235
|
-
while i < len(input_list):
|
|
236
|
-
if input_list[i] == "(":
|
|
237
|
-
# locate the beginning and end indices of the parenthetical group
|
|
238
|
-
start = i
|
|
239
|
-
stop = input_list.index(")", i)
|
|
240
|
-
|
|
241
|
-
# locate the number after the group, if any
|
|
242
|
-
if input_list[stop + 1].isnumeric():
|
|
243
|
-
num = int(input_list[stop + 1])
|
|
244
|
-
# skip past the parenthetical group once the loop is done
|
|
245
|
-
i = stop + 2
|
|
246
|
-
else:
|
|
247
|
-
num = 1
|
|
248
|
-
# skip past the parenthetical group once the loop is done
|
|
249
|
-
i = stop + 1
|
|
250
|
-
|
|
251
|
-
# loop through the elements / numbers contained in the group
|
|
252
|
-
for j in range(start + 1, stop):
|
|
253
|
-
if input_list[j].isalpha() and input_list[j + 1].isnumeric():
|
|
254
|
-
output_list.append(input_list[j])
|
|
255
|
-
output_list.append(str(int(input_list[j + 1]) * num))
|
|
256
|
-
elif input_list[j].isalpha():
|
|
257
|
-
output_list.append(input_list[j])
|
|
258
|
-
if num > 1:
|
|
259
|
-
output_list.append(str(num))
|
|
260
|
-
|
|
261
|
-
else:
|
|
262
|
-
output_list.append(input_list[i])
|
|
263
|
-
# advance to the next list element
|
|
264
|
-
i = i + 1
|
|
265
|
-
|
|
266
|
-
return output_list
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def _consolidate_formula(formula):
|
|
270
|
-
"""
|
|
271
|
-
Consolidate a formula into its simplest form, containing only one
|
|
272
|
-
instance of each element and no parentheses
|
|
273
|
-
|
|
274
|
-
Examples
|
|
275
|
-
--------
|
|
276
|
-
>>> _consolidate_formula('CH3(CH2)6CH3')
|
|
277
|
-
['C', 8, 'H', 18]
|
|
278
|
-
>>> _consolidate_formula('(Fe)2(SO4)4')
|
|
279
|
-
['Fe', 2, 'S', 4, 'O', 16]
|
|
280
|
-
>>> _consolidate_formula('Fe(OH)2+')
|
|
281
|
-
['Fe', 1, 'O', 2, 'H', 2, '+1']
|
|
282
|
-
|
|
283
|
-
"""
|
|
284
|
-
# perform validity check and return a list of the chemical formula's components
|
|
285
|
-
input_list = _remove_parentheses(formula)
|
|
286
|
-
output_list = []
|
|
287
|
-
|
|
288
|
-
for i in range(0, len(input_list)):
|
|
289
|
-
# is the item an element, a number, or a charge?
|
|
290
|
-
if input_list[i].isalpha():
|
|
291
|
-
# is it followed by a number?
|
|
292
|
-
try:
|
|
293
|
-
if input_list[i + 1].isnumeric():
|
|
294
|
-
quantity = input_list[i + 1]
|
|
295
|
-
else:
|
|
296
|
-
quantity = 1
|
|
297
|
-
except IndexError:
|
|
298
|
-
quantity = 1
|
|
299
|
-
|
|
300
|
-
# have we seen it before?
|
|
301
|
-
if input_list[i] in output_list:
|
|
302
|
-
# yes, so find it in the output list
|
|
303
|
-
index = output_list.index(input_list[i])
|
|
304
|
-
# add the quantity
|
|
305
|
-
output_list[index + 1] += int(quantity)
|
|
306
|
-
else:
|
|
307
|
-
# no, so add it and its quantity
|
|
308
|
-
output_list.append(input_list[i])
|
|
309
|
-
output_list.append(int(quantity))
|
|
310
|
-
|
|
311
|
-
# include any charge symbols
|
|
312
|
-
charge = get_formal_charge(formula)
|
|
313
|
-
if charge > 0:
|
|
314
|
-
output_list.append("+" + str(charge))
|
|
315
|
-
elif charge < 0:
|
|
316
|
-
output_list.append(str(charge))
|
|
317
|
-
|
|
318
|
-
return output_list
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
# Truth Functions
|
|
322
|
-
def is_valid_element(formula):
|
|
323
|
-
"""
|
|
324
|
-
Check whether a string is a valid atomic symbol
|
|
325
|
-
|
|
326
|
-
Parameters
|
|
327
|
-
----------
|
|
328
|
-
:formula: str
|
|
329
|
-
String representing an atomic symbol. First letter must be
|
|
330
|
-
uppercase, second letter must be lowercase.
|
|
331
|
-
|
|
332
|
-
Returns
|
|
333
|
-
-------
|
|
334
|
-
bool
|
|
335
|
-
True if the string is a valid atomic symbol. False otherwise.
|
|
336
|
-
|
|
337
|
-
Examples
|
|
338
|
-
--------
|
|
339
|
-
>>> is_valid_element('Cu')
|
|
340
|
-
True
|
|
341
|
-
>>> is_valid_element('Na+')
|
|
342
|
-
False
|
|
343
|
-
"""
|
|
344
|
-
if formula in atomic_numbers:
|
|
345
|
-
return True
|
|
346
|
-
else:
|
|
347
|
-
_invalid_formula("invalid element symbol")
|
|
348
|
-
return False
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
def is_valid_formula(formula):
|
|
352
|
-
"""
|
|
353
|
-
Check that a molecular formula is formatted correctly
|
|
354
|
-
|
|
355
|
-
Parameters
|
|
356
|
-
----------
|
|
357
|
-
formula: str
|
|
358
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
359
|
-
Valid molecular formulas must meet the following criteria:
|
|
360
|
-
|
|
361
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
362
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
363
|
-
'+', or '-'
|
|
364
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
365
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
366
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
367
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
368
|
-
#. Open parentheses must precede closed parentheses
|
|
369
|
-
|
|
370
|
-
Returns
|
|
371
|
-
-------
|
|
372
|
-
bool
|
|
373
|
-
True if the formula is valid. False otherwise.
|
|
374
|
-
|
|
375
|
-
Examples
|
|
376
|
-
--------
|
|
377
|
-
>>> is_valid_formula('Fe2(SO4)3')
|
|
378
|
-
True
|
|
379
|
-
>>> is_valid_formula('2Na+')
|
|
380
|
-
False
|
|
381
|
-
>>> is_valid_formula('HCO3-')
|
|
382
|
-
True
|
|
383
|
-
>>> is_valid_formula('Na+-')
|
|
384
|
-
False
|
|
385
|
-
>>> is_valid_formula('C10h12')
|
|
386
|
-
False
|
|
387
|
-
"""
|
|
388
|
-
|
|
389
|
-
try:
|
|
390
|
-
_check_formula(formula)
|
|
391
|
-
return True
|
|
392
|
-
except:
|
|
393
|
-
return False
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
def contains(formula, element):
|
|
397
|
-
"""
|
|
398
|
-
Check whether a formula contains a given element.
|
|
399
|
-
|
|
400
|
-
Parameters
|
|
401
|
-
----------
|
|
402
|
-
formula: str
|
|
403
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
404
|
-
Valid molecular formulas must meet the following criteria:
|
|
405
|
-
|
|
406
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
407
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
408
|
-
'+', or '-'
|
|
409
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
410
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
411
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
412
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
413
|
-
#. Open parentheses must precede closed parentheses
|
|
414
|
-
element: str
|
|
415
|
-
String representing the element to check for. Must be a valid element
|
|
416
|
-
name.
|
|
417
|
-
|
|
418
|
-
Returns
|
|
419
|
-
-------
|
|
420
|
-
bool
|
|
421
|
-
True if the formula contains the element. False otherwise.
|
|
422
|
-
|
|
423
|
-
Examples
|
|
424
|
-
--------
|
|
425
|
-
>>> contains('Fe2(SO4)3','Fe')
|
|
426
|
-
True
|
|
427
|
-
>>> contains('NaCOOH','S')
|
|
428
|
-
False
|
|
429
|
-
"""
|
|
430
|
-
if is_valid_element(element):
|
|
431
|
-
if element in get_elements(formula):
|
|
432
|
-
return True
|
|
433
|
-
else:
|
|
434
|
-
return False
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
# Information Retrieval Functions
|
|
438
|
-
def get_element_numbers(formula):
|
|
439
|
-
"""
|
|
440
|
-
Return the atomic numbers of the elements in a chemical formula
|
|
441
|
-
|
|
442
|
-
Parameters
|
|
443
|
-
----------
|
|
444
|
-
formula: str
|
|
445
|
-
String representing a chemical formula
|
|
446
|
-
|
|
447
|
-
Examples
|
|
448
|
-
--------
|
|
449
|
-
>>> get_element_numbers('FeSO4')
|
|
450
|
-
[26, 16, 8]
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
"""
|
|
454
|
-
# perform validity check and return a list of the chemical formula's components
|
|
455
|
-
input_list = get_elements(formula)
|
|
456
|
-
output_list = []
|
|
457
|
-
|
|
458
|
-
for item in input_list:
|
|
459
|
-
output_list.append(atomic_numbers[item][0])
|
|
460
|
-
|
|
461
|
-
return output_list
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
def get_element_names(formula):
|
|
465
|
-
"""
|
|
466
|
-
Return the names of the elements in a chemical formula
|
|
467
|
-
|
|
468
|
-
Parameters
|
|
469
|
-
----------
|
|
470
|
-
formula: str
|
|
471
|
-
String representing a chemical formula
|
|
472
|
-
|
|
473
|
-
Examples
|
|
474
|
-
--------
|
|
475
|
-
>>> get_element_names('FeSO4')
|
|
476
|
-
['Iron', 'Sulfur', 'Oxygen']
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
"""
|
|
480
|
-
# perform validity check and return a list of the chemical formula's components
|
|
481
|
-
input_list = get_elements(formula)
|
|
482
|
-
output_list = []
|
|
483
|
-
|
|
484
|
-
for item in input_list:
|
|
485
|
-
output_list.append(atomic_numbers[item][1])
|
|
486
|
-
|
|
487
|
-
return output_list
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
def hill_order(formula):
|
|
491
|
-
"""
|
|
492
|
-
Return a string representing the simplest form of 'formula'
|
|
493
|
-
in the Hill order (Carbon, Hydrgen, then other elements
|
|
494
|
-
in alphabetical order). If no Carbon is present, then
|
|
495
|
-
all elements are listed in alphabetical order.
|
|
496
|
-
|
|
497
|
-
NOTE: this function does NOT (yet) honor exceptions to the Hill Order
|
|
498
|
-
for acids, hydroxides, oxides, and ionic compounds. It follows the
|
|
499
|
-
rule above no matter what.
|
|
500
|
-
|
|
501
|
-
Examples
|
|
502
|
-
--------
|
|
503
|
-
>>> hill_order('CH2(CH3)4COOH')
|
|
504
|
-
'C6H15O2'
|
|
505
|
-
|
|
506
|
-
>>> hill_order('NaCl')
|
|
507
|
-
'ClNa'
|
|
508
|
-
|
|
509
|
-
>>> hill_order('NaHCO2') == hill_order('HCOONa')
|
|
510
|
-
True
|
|
511
|
-
|
|
512
|
-
>>> hill_order('Fe+2') == hill_order('Fe+3')
|
|
513
|
-
False
|
|
514
|
-
|
|
515
|
-
"""
|
|
516
|
-
# TODO - add exceptions for oxides (end in O2), acids (start with H),
|
|
517
|
-
# ions (cation first), and hydroxides (ends in OH)
|
|
518
|
-
temp_list = _consolidate_formula(formula)
|
|
519
|
-
hill = ""
|
|
520
|
-
|
|
521
|
-
# start the formula with C and H if Carbon is present
|
|
522
|
-
if "C" in temp_list:
|
|
523
|
-
for item in ["C", "H"]:
|
|
524
|
-
if item in temp_list:
|
|
525
|
-
index = temp_list.index(item)
|
|
526
|
-
hill += item
|
|
527
|
-
# copy the number only if greater than 1
|
|
528
|
-
if temp_list[index + 1] > 1:
|
|
529
|
-
hill += str(temp_list.pop(index + 1))
|
|
530
|
-
elif temp_list[index + 1] == 1:
|
|
531
|
-
temp_list.pop(index + 1)
|
|
532
|
-
temp_list.remove(item)
|
|
533
|
-
|
|
534
|
-
# convert any remaining list entries into tuples of (element,number)
|
|
535
|
-
# so they can be sorted
|
|
536
|
-
tuple_list = []
|
|
537
|
-
for item in temp_list:
|
|
538
|
-
index = temp_list.index(item)
|
|
539
|
-
try:
|
|
540
|
-
if item.isalpha():
|
|
541
|
-
tuple_list.append((item, temp_list[index + 1]))
|
|
542
|
-
except AttributeError:
|
|
543
|
-
continue
|
|
544
|
-
|
|
545
|
-
# put the remaining elements in alphabetical order
|
|
546
|
-
tuple_list.sort()
|
|
547
|
-
|
|
548
|
-
# add them to the formula
|
|
549
|
-
for item in tuple_list:
|
|
550
|
-
if item[1] == 1:
|
|
551
|
-
hill += str(item[0])
|
|
552
|
-
else:
|
|
553
|
-
hill += str(item[0]) + str(item[1])
|
|
554
|
-
|
|
555
|
-
# append the formal charge to the end of the formula, if not zero
|
|
556
|
-
charge = get_formal_charge(formula)
|
|
557
|
-
if charge != 0:
|
|
558
|
-
hill += str(charge)
|
|
559
|
-
|
|
560
|
-
return hill
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
def get_elements(formula):
|
|
564
|
-
"""
|
|
565
|
-
Return a list of strings representing the elements in a
|
|
566
|
-
molecular formula, with no duplicates.
|
|
567
|
-
|
|
568
|
-
Examples
|
|
569
|
-
--------
|
|
570
|
-
>>> get_elements('FeSO4')
|
|
571
|
-
['Fe', 'S', 'O']
|
|
572
|
-
>>> get_elements('CH3(CH2)4(CO)3')
|
|
573
|
-
['C', 'H', 'O']
|
|
574
|
-
|
|
575
|
-
See Also
|
|
576
|
-
--------
|
|
577
|
-
_check_formula
|
|
578
|
-
"""
|
|
579
|
-
# perform validity check and return a parsed list of the chemical formula
|
|
580
|
-
input_list = _consolidate_formula(formula)
|
|
581
|
-
output_list = []
|
|
582
|
-
|
|
583
|
-
for item in input_list:
|
|
584
|
-
if item in atomic_numbers:
|
|
585
|
-
output_list.append(item)
|
|
586
|
-
|
|
587
|
-
return output_list
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
def get_formal_charge(formula):
|
|
591
|
-
"""
|
|
592
|
-
Return the formal charge on a molecule based on its formula
|
|
593
|
-
|
|
594
|
-
Examples
|
|
595
|
-
--------
|
|
596
|
-
>>> get_formal_charge('Na+')
|
|
597
|
-
1
|
|
598
|
-
>>> get_formal_charge('PO4-3')
|
|
599
|
-
-3
|
|
600
|
-
>>> get_formal_charge('Fe+++')
|
|
601
|
-
3
|
|
602
|
-
|
|
603
|
-
See Also
|
|
604
|
-
--------
|
|
605
|
-
_check_formula
|
|
606
|
-
|
|
607
|
-
"""
|
|
608
|
-
# perform validity check and return a parsed list of the chemical formula
|
|
609
|
-
input_list = _check_formula(formula)
|
|
610
|
-
|
|
611
|
-
if "+" in input_list:
|
|
612
|
-
index = input_list.index("+")
|
|
613
|
-
try:
|
|
614
|
-
formal_charge = 1 * int(input_list[index + 1])
|
|
615
|
-
except IndexError:
|
|
616
|
-
formal_charge = 1
|
|
617
|
-
elif "-" in input_list:
|
|
618
|
-
index = input_list.index("-")
|
|
619
|
-
try:
|
|
620
|
-
formal_charge = -1 * int(input_list[index + 1])
|
|
621
|
-
except IndexError:
|
|
622
|
-
formal_charge = -1
|
|
623
|
-
elif "+" in input_list[-1]:
|
|
624
|
-
formal_charge = int(1 * input_list[-1].count("+"))
|
|
625
|
-
elif "-" in input_list[-1]:
|
|
626
|
-
formal_charge = int(-1 * input_list[-1].count("-"))
|
|
627
|
-
else:
|
|
628
|
-
formal_charge = 0
|
|
629
|
-
|
|
630
|
-
return formal_charge
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
def get_element_mole_ratio(formula, element):
|
|
634
|
-
"""
|
|
635
|
-
compute the moles of a specific element per mole of formula
|
|
636
|
-
|
|
637
|
-
Parameters
|
|
638
|
-
----------
|
|
639
|
-
formula: str
|
|
640
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
641
|
-
Valid molecular formulas must meet the following criteria:
|
|
642
|
-
|
|
643
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
644
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
645
|
-
'+', or '-'
|
|
646
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
647
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
648
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
649
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
650
|
-
#. Open parentheses must precede closed parentheses
|
|
651
|
-
element: str
|
|
652
|
-
String representing the element to check for. Must be a valid element
|
|
653
|
-
name.
|
|
654
|
-
|
|
655
|
-
Returns
|
|
656
|
-
-------
|
|
657
|
-
number
|
|
658
|
-
The number of moles of element per mole of formula, mol/mol.
|
|
659
|
-
|
|
660
|
-
>>> get_element_mole_ratio('NaCl','Na')
|
|
661
|
-
1
|
|
662
|
-
>>> get_element_mole_ratio('H2O','H')
|
|
663
|
-
2
|
|
664
|
-
>>> get_element_mole_ratio('H2O','Br')
|
|
665
|
-
0
|
|
666
|
-
>>> get_element_mole_ratio('CH3CH2CH3','C')
|
|
667
|
-
3
|
|
668
|
-
|
|
669
|
-
See Also
|
|
670
|
-
--------
|
|
671
|
-
contains
|
|
672
|
-
consolidate_formula
|
|
673
|
-
get_element_weight
|
|
674
|
-
get_element_weight_fraction
|
|
675
|
-
|
|
676
|
-
"""
|
|
677
|
-
# perform validity check and return a parsed list of the chemical formula
|
|
678
|
-
if contains(formula, element):
|
|
679
|
-
input_list = _consolidate_formula(formula)
|
|
680
|
-
index = input_list.index(element)
|
|
681
|
-
moles = input_list[index + 1]
|
|
682
|
-
# return 0 weight if the element isn't present in the formula
|
|
683
|
-
else:
|
|
684
|
-
moles = 0
|
|
685
|
-
|
|
686
|
-
return moles
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
def get_element_weight(formula, element):
|
|
690
|
-
"""
|
|
691
|
-
compute the weight of a specific element in a formula
|
|
692
|
-
|
|
693
|
-
Parameters
|
|
694
|
-
----------
|
|
695
|
-
formula: str
|
|
696
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
697
|
-
Valid molecular formulas must meet the following criteria:
|
|
698
|
-
|
|
699
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
700
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
701
|
-
'+', or '-'
|
|
702
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
703
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
704
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
705
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
706
|
-
#. Open parentheses must precede closed parentheses
|
|
707
|
-
element: str
|
|
708
|
-
String representing the element to check for. Must be a valid element
|
|
709
|
-
name.
|
|
710
|
-
|
|
711
|
-
Returns
|
|
712
|
-
-------
|
|
713
|
-
number
|
|
714
|
-
The weight of the specified element within the formula, g/mol.
|
|
715
|
-
|
|
716
|
-
>>> get_element_weight('NaCl','Na')
|
|
717
|
-
22.98977
|
|
718
|
-
>>> get_element_weight('H2O','H')
|
|
719
|
-
2.01588
|
|
720
|
-
>>> get_element_weight('H2O','Br')
|
|
721
|
-
0.0
|
|
722
|
-
>>> get_element_weight('CH3CH2CH3','C')
|
|
723
|
-
36.0321
|
|
724
|
-
|
|
725
|
-
See Also
|
|
726
|
-
--------
|
|
727
|
-
contains
|
|
728
|
-
_consolidate_formula
|
|
729
|
-
elements
|
|
730
|
-
get_element_mole_ratio
|
|
731
|
-
|
|
732
|
-
"""
|
|
733
|
-
# find the number of moles of element per mole of formula
|
|
734
|
-
moles = get_element_mole_ratio(formula, element)
|
|
735
|
-
|
|
736
|
-
if moles != 0:
|
|
737
|
-
# import elements.py - used to retreive various molecular data
|
|
738
|
-
from pyEQL.elements import ELEMENTS
|
|
739
|
-
|
|
740
|
-
# look up the molecular weight for the element
|
|
741
|
-
mass = ELEMENTS[element].mass
|
|
742
|
-
|
|
743
|
-
wt = mass * moles
|
|
744
|
-
else:
|
|
745
|
-
wt = 0.0
|
|
746
|
-
|
|
747
|
-
return wt
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
def get_element_weight_fraction(formula, element):
|
|
751
|
-
"""
|
|
752
|
-
compute the weight fraction of a specific element in a formula
|
|
753
|
-
|
|
754
|
-
Parameters
|
|
755
|
-
----------
|
|
756
|
-
formula: str
|
|
757
|
-
String representing a molecular formula. e.g. 'H2O' or 'FeOH+'
|
|
758
|
-
Valid molecular formulas must meet the following criteria:
|
|
759
|
-
|
|
760
|
-
#. Are composed of valid atomic symbols that start with capital letters
|
|
761
|
-
#. Contain no non-alphanumeric characters other than '(', ')',
|
|
762
|
-
'+', or '-'
|
|
763
|
-
#. If a '+' or '-' is present, the formula must contain ONLY '+' or
|
|
764
|
-
'-' (e.g. 'Na+-' is invalid) and the formula must end with either
|
|
765
|
-
a series of charges (e.g. 'Fe+++') or a numeric charge (e.g. 'Fe+3')
|
|
766
|
-
#. Formula must contain matching numbers of '(' and ')'
|
|
767
|
-
#. Open parentheses must precede closed parentheses
|
|
768
|
-
element: str
|
|
769
|
-
String representing the element to check for. Must be a valid element
|
|
770
|
-
name.
|
|
771
|
-
|
|
772
|
-
Returns
|
|
773
|
-
-------
|
|
774
|
-
number
|
|
775
|
-
The weight fraction of the specified element within the formula.
|
|
776
|
-
|
|
777
|
-
>>> get_element_weight_fraction('NaCl','Na')
|
|
778
|
-
0.39337...
|
|
779
|
-
>>> get_element_weight_fraction('H2O','H')
|
|
780
|
-
0.111898...
|
|
781
|
-
>>> get_element_weight_fraction('H2O','Br')
|
|
782
|
-
0.0
|
|
783
|
-
>>> get_element_weight_fraction('CH3CH2CH3','C')
|
|
784
|
-
0.8171355...
|
|
785
|
-
|
|
786
|
-
See Also
|
|
787
|
-
--------
|
|
788
|
-
get_element_weight
|
|
789
|
-
contains
|
|
790
|
-
_consolidate_formula
|
|
791
|
-
elements
|
|
792
|
-
|
|
793
|
-
"""
|
|
794
|
-
# calculate the element weight in the formula
|
|
795
|
-
wt = get_element_weight(formula, element)
|
|
796
|
-
|
|
797
|
-
# calculate the fraction
|
|
798
|
-
frac = wt / get_molecular_weight(formula)
|
|
799
|
-
|
|
800
|
-
return frac
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
def get_molecular_weight(formula):
|
|
804
|
-
"""
|
|
805
|
-
compute the molecular weight of a formula
|
|
806
|
-
|
|
807
|
-
>>> get_molecular_weight('Na+')
|
|
808
|
-
22.98977
|
|
809
|
-
>>> get_molecular_weight('H2O')
|
|
810
|
-
18.01528
|
|
811
|
-
>>> get_molecular_weight('CH3CH2CH3')
|
|
812
|
-
44.09562
|
|
813
|
-
|
|
814
|
-
See Also
|
|
815
|
-
--------
|
|
816
|
-
_consolidate_formula
|
|
817
|
-
elements
|
|
818
|
-
|
|
819
|
-
"""
|
|
820
|
-
# import elements.py - used to retreive various molecular data
|
|
821
|
-
from pyEQL.elements import ELEMENTS
|
|
822
|
-
|
|
823
|
-
# perform validity check and return a parsed list of the chemical formula
|
|
824
|
-
input_list = _consolidate_formula(formula)
|
|
825
|
-
mw = 0
|
|
826
|
-
|
|
827
|
-
for item in input_list:
|
|
828
|
-
try:
|
|
829
|
-
if item.isalpha():
|
|
830
|
-
index = input_list.index(item)
|
|
831
|
-
quantity = input_list[index + 1]
|
|
832
|
-
# look up the molecular weight for the element
|
|
833
|
-
mass = ELEMENTS[item].mass
|
|
834
|
-
mw += mass * quantity
|
|
835
|
-
|
|
836
|
-
# if the list item is a number or a charge, move on
|
|
837
|
-
except AttributeError:
|
|
838
|
-
pass
|
|
839
|
-
|
|
840
|
-
return mw
|
|
841
|
-
|
|
842
|
-
# Output functions
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
def print_latex(formula):
|
|
846
|
-
"""
|
|
847
|
-
Print a LaTeX - formatted version of the formula
|
|
848
|
-
|
|
849
|
-
Examples
|
|
850
|
-
---------
|
|
851
|
-
>>> print_latex('Fe2SO4')
|
|
852
|
-
Fe_2SO_4
|
|
853
|
-
>>> print_latex('CH3CH2CH3')
|
|
854
|
-
CH_3CH_2CH_3
|
|
855
|
-
>>> print_latex('Fe2(OH)2+2')
|
|
856
|
-
Fe_2(OH)_2^+^2
|
|
857
|
-
|
|
858
|
-
"""
|
|
859
|
-
output = ""
|
|
860
|
-
for i in range(len(formula)):
|
|
861
|
-
# insert LaTeX subscripts (underscore) before all numbers, unless they start
|
|
862
|
-
# the formula or follow a charge symbol
|
|
863
|
-
if formula[i].isnumeric() and i > 0:
|
|
864
|
-
# insert superscript before a charge
|
|
865
|
-
if formula[i - 1] == "+" or formula[i - 1] == "-":
|
|
866
|
-
output += "^"
|
|
867
|
-
else:
|
|
868
|
-
output += "_"
|
|
869
|
-
|
|
870
|
-
# insert superscripts before charges
|
|
871
|
-
if formula[i] == "+" or formula[i] == "-":
|
|
872
|
-
output += "^"
|
|
873
|
-
|
|
874
|
-
# pass the rest of the formula to output
|
|
875
|
-
output += formula[i]
|
|
876
|
-
|
|
877
|
-
print(output)
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
# Dictionary to correlate atomic symbols, names, and numbers
|
|
881
|
-
atomic_numbers = {
|
|
882
|
-
"H": (1, "Hydrogen"),
|
|
883
|
-
"He": (2, "Helium"),
|
|
884
|
-
"Li": (3, "Lithium"),
|
|
885
|
-
"Be": (4, "Beryllium"),
|
|
886
|
-
"B": (5, "Boron"),
|
|
887
|
-
"C": (6, "Carbon"),
|
|
888
|
-
"N": (7, "Nitrogen"),
|
|
889
|
-
"O": (8, "Oxygen"),
|
|
890
|
-
"F": (9, "Fluorine"),
|
|
891
|
-
"Ne": (10, "Neon"),
|
|
892
|
-
"Na": (11, "Sodium"),
|
|
893
|
-
"Mg": (12, "Magnesium"),
|
|
894
|
-
"Al": (13, "Aluminum"),
|
|
895
|
-
"Si": (14, "Silicon"),
|
|
896
|
-
"P": (15, "Phosphorus"),
|
|
897
|
-
"S": (16, "Sulfur"),
|
|
898
|
-
"Cl": (17, "Chlorine"),
|
|
899
|
-
"Ar": (18, "Argon"),
|
|
900
|
-
"K": (19, "Potassium"),
|
|
901
|
-
"Ca": (20, "Calcium"),
|
|
902
|
-
"Sc": (21, "Scandium"),
|
|
903
|
-
"Ti": (22, "Titanium"),
|
|
904
|
-
"V": (23, "Vanadium"),
|
|
905
|
-
"Cr": (24, "Chromium"),
|
|
906
|
-
"Mn": (25, "Manganese"),
|
|
907
|
-
"Fe": (26, "Iron"),
|
|
908
|
-
"Co": (27, "Cobalt"),
|
|
909
|
-
"Ni": (28, "Nickel"),
|
|
910
|
-
"Cu": (29, "Copper"),
|
|
911
|
-
"Zn": (30, "Zinc"),
|
|
912
|
-
"Ga": (31, "Gallium"),
|
|
913
|
-
"Ge": (32, "Germanium"),
|
|
914
|
-
"As": (33, "Arsenic"),
|
|
915
|
-
"Se": (34, "Selenium"),
|
|
916
|
-
"Br": (35, "Bromine"),
|
|
917
|
-
"Kr": (36, "Krypton"),
|
|
918
|
-
"Rb": (37, "Rubidium"),
|
|
919
|
-
"Sr": (38, "Strontium"),
|
|
920
|
-
"Y": (39, "Yttrium"),
|
|
921
|
-
"Zr": (40, "Zirconium"),
|
|
922
|
-
"Nb": (41, "Niobium"),
|
|
923
|
-
"Mo": (42, "Molybdenum"),
|
|
924
|
-
"Tc": (43, "Technetium"),
|
|
925
|
-
"Ru": (44, "Ruthenium"),
|
|
926
|
-
"Rh": (45, "Rhodium"),
|
|
927
|
-
"Pd": (46, "Palladium"),
|
|
928
|
-
"Ag": (47, "Silver"),
|
|
929
|
-
"Cd": (48, "Cadmium"),
|
|
930
|
-
"In": (49, "Indium"),
|
|
931
|
-
"Sn": (50, "Tin"),
|
|
932
|
-
"Sb": (51, "Antimony"),
|
|
933
|
-
"Te": (52, "Tellurium"),
|
|
934
|
-
"I": (53, "Iodine"),
|
|
935
|
-
"Xe": (54, "Xenon"),
|
|
936
|
-
"Cs": (55, "Cesium"),
|
|
937
|
-
"Ba": (56, "Barium"),
|
|
938
|
-
"La": (57, "Lanthanum"),
|
|
939
|
-
"Ce": (58, "Cerium"),
|
|
940
|
-
"Pr": (59, "Praseodymium"),
|
|
941
|
-
"Nd": (60, "Neodymium"),
|
|
942
|
-
"Pm": (61, "Promethium"),
|
|
943
|
-
"Sm": (62, "Samarium"),
|
|
944
|
-
"Eu": (63, "Europium"),
|
|
945
|
-
"Gd": (64, "Gadolinium"),
|
|
946
|
-
"Tb": (65, "Terbium"),
|
|
947
|
-
"Dy": (66, "Dysprosium"),
|
|
948
|
-
"Ho": (67, "Holmium"),
|
|
949
|
-
"Er": (68, "Erbium"),
|
|
950
|
-
"Tm": (69, "Thulium"),
|
|
951
|
-
"Yb": (70, "Ytterbium"),
|
|
952
|
-
"Lu": (71, "Lutetium"),
|
|
953
|
-
"Hf": (72, "Hafnium"),
|
|
954
|
-
"Ta": (73, "Tantalum"),
|
|
955
|
-
"W": (74, "Tungsten"),
|
|
956
|
-
"Re": (75, "Rhenium"),
|
|
957
|
-
"Os": (76, "Osmium"),
|
|
958
|
-
"Ir": (77, "Iridium"),
|
|
959
|
-
"Pt": (78, "Platinum"),
|
|
960
|
-
"Au": (79, "Gold"),
|
|
961
|
-
"Hg": (80, "Mercury"),
|
|
962
|
-
"Tl": (81, "Thallium"),
|
|
963
|
-
"Pb": (82, "Lead"),
|
|
964
|
-
"Bi": (83, "Bismuth"),
|
|
965
|
-
"Po": (84, "Polonium"),
|
|
966
|
-
"At": (85, "Astatine"),
|
|
967
|
-
"Rn": (86, "Radon"),
|
|
968
|
-
"Fr": (87, "Francium"),
|
|
969
|
-
"Ra": (88, "Radium"),
|
|
970
|
-
"Ac": (89, "Actinium"),
|
|
971
|
-
"Th": (90, "Thorium"),
|
|
972
|
-
"Pa": (91, "Protactinium"),
|
|
973
|
-
"U": (92, "Uranium"),
|
|
974
|
-
"Np": (93, "Neptunium"),
|
|
975
|
-
"Pu": (94, "Plutonium"),
|
|
976
|
-
"Am": (95, "Americium"),
|
|
977
|
-
"Cm": (96, "Curium"),
|
|
978
|
-
"Bk": (97, "Berkelium"),
|
|
979
|
-
"Cf": (98, "Californium"),
|
|
980
|
-
"Es": (99, "Einsteinium"),
|
|
981
|
-
"Fm": (100, "Fermium"),
|
|
982
|
-
"Md": (101, "Mendelevium"),
|
|
983
|
-
"No": (102, "Nobelium"),
|
|
984
|
-
"Lr": (103, "Lawrencium"),
|
|
985
|
-
"Rf": (104, "Rutherfordium"),
|
|
986
|
-
"Db": (105, "Dubnium"),
|
|
987
|
-
"Sg": (106, "Seaborgium"),
|
|
988
|
-
"Bh": (107, "Bohrium"),
|
|
989
|
-
"Hs": (108, "Hassium"),
|
|
990
|
-
"Mt": (109, "Meitnerium"),
|
|
991
|
-
"Ds": (110, "Darmstadtium"),
|
|
992
|
-
"Rg": (111, "Roentgenium"),
|
|
993
|
-
"Cn": (112, "Copernicium"),
|
|
994
|
-
"Uut": (113, "Ununtrium"),
|
|
995
|
-
"Fl": (114, "Flerovium"),
|
|
996
|
-
"Uup": (115, "Ununpentium"),
|
|
997
|
-
"Lv": (116, "Livermorium"),
|
|
998
|
-
"Uus": (117, "Ununseptium"),
|
|
999
|
-
"Uuo": (118, "Ununoctium"),
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
# TODO - turn doctest back on when the nosigint error is gone
|
|
1003
|
-
# if __name__ == "__main__":
|
|
1004
|
-
# import doctest
|
|
1005
|
-
# doctest.testfile('tests/test_chemical_formula.rst')
|
|
1006
|
-
# doctest.testmod()
|