pyEQL 0.5.2__py3-none-any.whl → 1.1.0__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 +165 -0
- pyEQL-1.1.0.dist-info/AUTHORS.md +13 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/COPYING +1 -1
- pyEQL-0.5.2.dist-info/LICENSE → pyEQL-1.1.0.dist-info/LICENSE.txt +3 -7
- pyEQL-1.1.0.dist-info/METADATA +129 -0
- pyEQL-1.1.0.dist-info/RECORD +27 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/WHEEL +2 -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.1.0.dist-info}/top_level.txt +0 -0
pyEQL/equilibrium.py
CHANGED
|
@@ -1,137 +1,107 @@
|
|
|
1
1
|
"""
|
|
2
2
|
pyEQL methods for chemical equilibrium calculations (e.g. acid/base, reactions,
|
|
3
|
-
redox, complexation, etc.)
|
|
3
|
+
redox, complexation, etc.).
|
|
4
4
|
|
|
5
5
|
NOTE: these methods are not currently used but are here for the future.
|
|
6
6
|
|
|
7
|
-
:copyright: 2013-
|
|
7
|
+
:copyright: 2013-2024 by Ryan S. Kingsbury
|
|
8
8
|
:license: LGPL, see LICENSE for more details.
|
|
9
9
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
# Dependencies
|
|
13
12
|
# import libraries for scientific functions
|
|
14
|
-
import math
|
|
15
|
-
|
|
16
|
-
# the pint unit registry
|
|
17
|
-
from pyEQL import unit
|
|
18
|
-
|
|
19
|
-
# logging system
|
|
20
13
|
import logging
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
from pyEQL.logging_system import Unique
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
unique = Unique()
|
|
27
|
-
logger.addFilter(unique)
|
|
28
|
-
|
|
29
|
-
# add a handler for console output, since pyEQL is meant to be used interactively
|
|
30
|
-
ch = logging.StreamHandler()
|
|
15
|
+
import numpy as np
|
|
31
16
|
|
|
32
|
-
|
|
33
|
-
formatter = logging.Formatter("(%(name)s) - %(levelname)s - %(message)s")
|
|
34
|
-
|
|
35
|
-
# add formatter to the handler
|
|
36
|
-
ch.setFormatter(formatter)
|
|
37
|
-
logger.addHandler(ch)
|
|
17
|
+
from pyEQL import ureg
|
|
38
18
|
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
39
20
|
|
|
40
|
-
|
|
21
|
+
# TODO - not used. Remove?
|
|
22
|
+
SPECIES_ALIAISES = {
|
|
23
|
+
"Sodium": "Na+",
|
|
24
|
+
"Potassium": "K+",
|
|
25
|
+
"Calcium": "Ca+2",
|
|
26
|
+
"Barium": "Ba+2",
|
|
27
|
+
"Strontium": "Sr+2",
|
|
28
|
+
"Magnesium": "Mg+2",
|
|
29
|
+
"Chloride": "Cl-",
|
|
30
|
+
"Fluoride": "F-",
|
|
31
|
+
"Nitrate": "NO3-",
|
|
32
|
+
"Ammonium": "NH4+",
|
|
33
|
+
"Sulfate": "SO4-2",
|
|
34
|
+
"Phosphate": "PO4-3",
|
|
35
|
+
"Carbonate": "CO3-2",
|
|
36
|
+
"Bicarbonate": "HCO3-",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15 K")):
|
|
41
41
|
"""
|
|
42
|
-
Calculate a parameter for
|
|
43
|
-
coefficients c1,c2,c3,c4,and c5.
|
|
44
|
-
|
|
45
|
-
Parameters
|
|
46
|
-
----------
|
|
47
|
-
c1, c2, c3, c4, c5: float
|
|
48
|
-
Temperature-dependent coefficients for the pitzer parameter of
|
|
49
|
-
interest.
|
|
50
|
-
temp: Quantity
|
|
51
|
-
The temperature at which the Pitzer parameter is to be calculated
|
|
52
|
-
temp_ref: Quantity, optional
|
|
53
|
-
The reference temperature on which the parameters are based.
|
|
54
|
-
298.15 K if omitted.
|
|
55
|
-
|
|
56
|
-
As described in the PHREEQC documentation
|
|
42
|
+
Calculate a parameter for the Pitzer model based on temperature-dependent coefficients c1,c2,c3,c4,and c5.
|
|
57
43
|
|
|
44
|
+
Args:
|
|
45
|
+
c1, c2, c3, c4, c5 (float): Temperature-dependent coefficients for the pitzer parameter of interest.
|
|
46
|
+
temp (Quantity): The temperature at which the Pitzer parameter is to be calculated.
|
|
47
|
+
temp_ref (Quantity, optional): The reference temperature on which the parameters are based. Defaults to 298.15 K if omitted.
|
|
58
48
|
|
|
49
|
+
Note:
|
|
50
|
+
As described in the PHREEQC documentation.
|
|
59
51
|
"""
|
|
60
|
-
|
|
52
|
+
return (
|
|
61
53
|
c1
|
|
62
54
|
+ c2 * (1 / temp + 1 / temp_ref)
|
|
63
|
-
+ c2 *
|
|
55
|
+
+ c2 * np.log(temp / temp_ref)
|
|
64
56
|
+ c3 * (temp - temp_ref)
|
|
65
|
-
+ c4 * (temp
|
|
66
|
-
+ c5 * (temp
|
|
57
|
+
+ c4 * (temp**2 - temp_ref**2)
|
|
58
|
+
+ c5 * (temp**-2 - temp_ref**-2)
|
|
67
59
|
)
|
|
68
60
|
|
|
69
|
-
return pitzer_param
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def adjust_temp_vanthoff(
|
|
73
|
-
equilibrium_constant, enthalpy, temperature, reference_temperature=25 * unit("degC")
|
|
74
|
-
):
|
|
75
|
-
"""(float,float,number, optional number) -> float
|
|
76
61
|
|
|
62
|
+
def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_temperature=ureg.Quantity(25, "degC")):
|
|
63
|
+
r"""
|
|
77
64
|
Adjust a reaction equilibrium constant from one temperature to another.
|
|
78
65
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
The enthalpy change (delta H) for the reaction in kJ/mol. Assumed
|
|
85
|
-
independent of temperature (see Notes).
|
|
86
|
-
temperature : Quantity
|
|
87
|
-
the desired reaction temperature in degrees Celsius
|
|
88
|
-
reference_temperature : Quantity, optional
|
|
89
|
-
the temperature at which equilibrium_constant is valid. (25 degrees C if omitted).
|
|
90
|
-
|
|
91
|
-
Returns
|
|
92
|
-
-------
|
|
93
|
-
float
|
|
94
|
-
adjusted reaction equilibrium constant
|
|
66
|
+
Args:
|
|
67
|
+
equilibrium_constant (float): The reaction equilibrium constant for the reaction.
|
|
68
|
+
enthalpy (Quantity): The enthalpy change (delta H) for the reaction in kJ/mol. Assumed independent of temperature (see Notes).
|
|
69
|
+
temperature (Quantity): The desired reaction temperature in degrees Celsius.
|
|
70
|
+
reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
|
|
95
71
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
This function implements the Van't Hoff equation to adjust measured
|
|
99
|
-
equilibrium constants to other temperatures.
|
|
72
|
+
Returns:
|
|
73
|
+
float: The adjusted reaction equilibrium constant.
|
|
100
74
|
|
|
101
|
-
|
|
75
|
+
Note:
|
|
76
|
+
This function implements the Van't Hoff equation to adjust measured equilibrium constants to other temperatures.
|
|
102
77
|
|
|
103
|
-
|
|
78
|
+
.. math::
|
|
79
|
+
ln(K2 / K1) = {\delta H \over R} ( {1 \over T_1} - {1 \over T_2} )
|
|
104
80
|
|
|
105
|
-
|
|
106
|
-
over the range of interest.[1]
|
|
81
|
+
This implementation assumes that the enthalpy is independent of temperature over the range of interest.
|
|
107
82
|
|
|
108
|
-
|
|
109
|
-
Wiley Interscience, 1996.
|
|
83
|
+
References:
|
|
84
|
+
Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 53. Wiley Interscience, 1996.
|
|
110
85
|
|
|
111
|
-
Examples
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
0.00203566...
|
|
86
|
+
Examples:
|
|
87
|
+
>>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC'),ureg.Quantity(' 25degC')) #doctest: +ELLIPSIS
|
|
88
|
+
0.00203566...
|
|
115
89
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
>>> adjust_temp_vanthoff(0.15,-197.6*unit('kJ/mol'),42*unit('degC')) #doctest: +ELLIPSIS
|
|
119
|
-
0.00203566...
|
|
90
|
+
If the 'ref_temperature' parameter is omitted, a default of 25 C is used.
|
|
120
91
|
|
|
92
|
+
>>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC')) #doctest: +ELLIPSIS
|
|
93
|
+
0.00203566...
|
|
121
94
|
"""
|
|
122
|
-
output = equilibrium_constant *
|
|
123
|
-
enthalpy
|
|
124
|
-
/ unit.R
|
|
125
|
-
* (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
|
|
95
|
+
output = equilibrium_constant * np.exp(
|
|
96
|
+
enthalpy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
|
|
126
97
|
)
|
|
127
98
|
|
|
128
|
-
logger.
|
|
129
|
-
"Adjusted equilibrium constant K=%s from %s to %s degrees Celsius with Delta H = %s. "
|
|
130
|
-
"Adjusted K = %s % equilibrium_constant,reference_temperature,temperature,enthalpy,output"
|
|
99
|
+
logger.debug(
|
|
100
|
+
"Adjusted equilibrium constant K=%s from %s to %s degrees Celsius with Delta H = %s. Adjusted K = %s % equilibrium_constant,reference_temperature,temperature,enthalpy,output"
|
|
131
101
|
)
|
|
132
102
|
|
|
133
|
-
logger.
|
|
134
|
-
"Van't Hoff equation assumes enthalpy is independent of temperature over the range of interest"
|
|
103
|
+
logger.info(
|
|
104
|
+
"Note that the Van't Hoff equation assumes enthalpy is independent of temperature over the range of interest"
|
|
135
105
|
)
|
|
136
106
|
return output
|
|
137
107
|
|
|
@@ -140,168 +110,118 @@ def adjust_temp_arrhenius(
|
|
|
140
110
|
rate_constant,
|
|
141
111
|
activation_energy,
|
|
142
112
|
temperature,
|
|
143
|
-
reference_temperature=25
|
|
113
|
+
reference_temperature=ureg.Quantity(25, "degC"),
|
|
144
114
|
):
|
|
145
|
-
"""
|
|
146
|
-
|
|
115
|
+
r"""
|
|
147
116
|
Adjust a reaction equilibrium constant from one temperature to another.
|
|
148
117
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Returns
|
|
162
|
-
-------
|
|
163
|
-
Quantity
|
|
164
|
-
The adjusted reaction equilibrium constant
|
|
165
|
-
|
|
166
|
-
See Also
|
|
167
|
-
--------
|
|
168
|
-
kelvin
|
|
169
|
-
|
|
170
|
-
Notes
|
|
171
|
-
-----
|
|
172
|
-
This function implements the Arrhenius equation to adjust measured rate
|
|
173
|
-
constants to other temperatures. [1]
|
|
174
|
-
|
|
175
|
-
.. math::
|
|
176
|
-
|
|
177
|
-
ln(K2 / K1) = {E_a \\over R} ( {1 \\over T_1} - {1 \\over T_2} )
|
|
178
|
-
|
|
179
|
-
.. [1] http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/\
|
|
180
|
-
Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
|
|
181
|
-
TODO - add better reference
|
|
182
|
-
|
|
183
|
-
Examples
|
|
184
|
-
--------
|
|
185
|
-
>>> adjust_temp_arrhenius(7,900*unit('kJ/mol'),37*unit('degC'),97*unit('degC')) #doctest: +ELLIPSIS
|
|
186
|
-
1.8867225...e-24
|
|
118
|
+
Args:
|
|
119
|
+
rate_constant (Quantity): The parameter value (usually a rate constant) being adjusted.
|
|
120
|
+
activation_energy (Quantity): The activation energy of the process, in kJ/mol.
|
|
121
|
+
temperature (Quantity): The desired reaction temperature.
|
|
122
|
+
reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Quantity: The adjusted reaction equilibrium constant.
|
|
126
|
+
|
|
127
|
+
Notes:
|
|
128
|
+
This function implements the Arrhenius equation to adjust measured rate constants to other temperatures.
|
|
129
|
+
TODO - add better reference
|
|
187
130
|
|
|
131
|
+
.. math::
|
|
132
|
+
ln(\frac{K2}{K1}) = \frac{E_a}{R} ( \frac{1}{T_{1}} - {\frac{1}{T_2}} )
|
|
133
|
+
|
|
134
|
+
References:
|
|
135
|
+
http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
|
|
136
|
+
|
|
137
|
+
Examples:
|
|
138
|
+
>>> adjust_temp_arrhenius(7,900*ureg.Quantity('kJ/mol'),37*ureg.Quantity('degC'),97*ureg.Quantity('degC')) #doctest: +ELLIPSIS
|
|
139
|
+
1.8867225...e-24
|
|
188
140
|
"""
|
|
189
|
-
output = rate_constant *
|
|
190
|
-
activation_energy
|
|
191
|
-
/ unit.R
|
|
192
|
-
* (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
|
|
141
|
+
output = rate_constant * np.exp(
|
|
142
|
+
activation_energy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
|
|
193
143
|
)
|
|
194
144
|
|
|
195
|
-
logger.
|
|
196
|
-
"Adjusted parameter
|
|
197
|
-
"
|
|
145
|
+
logger.debug(
|
|
146
|
+
f"Adjusted parameter {rate_constant} from {reference_temperature} to {temperature} degrees Celsius with"
|
|
147
|
+
f"Activation Energy = {activation_energy}s kJ/mol. Adjusted value = {output}"
|
|
198
148
|
)
|
|
199
149
|
|
|
200
150
|
return output
|
|
201
151
|
|
|
202
152
|
|
|
203
153
|
def alpha(n, pH, pKa_list):
|
|
204
|
-
"""
|
|
205
|
-
Returns the acid-base distribution coefficient (alpha) of an acid in the
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
Notes
|
|
227
|
-
-----
|
|
228
|
-
The acid-base distribution coefficient is calculated as follows:[1]
|
|
229
|
-
|
|
230
|
-
.. math::
|
|
231
|
-
|
|
232
|
-
\\alpha_n = {term_n \\over [H+]^n + k_{a1}[H+]^n-1 + k_{a1}k_{a2}[H+]^n-2 ... k_{a1}k_{a2}...k_{an} }
|
|
233
|
-
|
|
234
|
-
Where :math: '\\term_n' refers to the nth term in the denominator, starting from 0
|
|
235
|
-
|
|
236
|
-
.. [1] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed,
|
|
237
|
-
pp 127-130. Wiley Interscience, 1996.
|
|
238
|
-
|
|
239
|
-
Examples
|
|
240
|
-
--------
|
|
241
|
-
>>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
|
|
242
|
-
0.999...
|
|
243
|
-
|
|
244
|
-
The sum of all alpha values should equal 1
|
|
245
|
-
|
|
246
|
-
>>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
247
|
-
0.021...
|
|
248
|
-
>>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
249
|
-
0.979...
|
|
250
|
-
>>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
251
|
-
2.043...e-09
|
|
252
|
-
|
|
253
|
-
If pH is equal to one of the pKa values the function should return 0.5.
|
|
254
|
-
|
|
255
|
-
>>> alpha(1,6.35,[6.35,10.33])
|
|
256
|
-
0.5
|
|
257
|
-
|
|
258
|
-
# The function will return an error if the number ofpKa's is less than n.
|
|
259
|
-
#
|
|
260
|
-
# >>> alpha(2,8,[])
|
|
261
|
-
# ERROR: insufficient number of pKa values given
|
|
262
|
-
# 0.5
|
|
154
|
+
r"""
|
|
155
|
+
Returns the acid-base distribution coefficient (alpha) of an acid in the n-deprotonated form at a given pH.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
n (int): The number of protons that have been lost by the desired form of the acid. Also the subscript on the
|
|
159
|
+
alpha value. E.g. for bicarbonate (HCO3-), n=1 because 1 proton has been lost from the fully-protonated
|
|
160
|
+
carbonic acid (H2CO3) form.
|
|
161
|
+
pH (float or int): The pH of the solution.
|
|
162
|
+
pKa_list (list of floats or ints): The pKa values (negative log of equilibrium constants) for the acid of
|
|
163
|
+
interest. There must be a minimum of n pKa values in the list.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
float: The fraction of total acid present in the specified form.
|
|
167
|
+
|
|
168
|
+
Notes:
|
|
169
|
+
The acid-base coefficient is calculated as follows: [stm]_
|
|
170
|
+
|
|
171
|
+
.. math::
|
|
172
|
+
|
|
173
|
+
\alpha_n = \frac{term_n}{[H+]^n + k_{a1}[H+]^{n-1} + k_{a1}k_{a2}[H+]^{n-2} ... k_{a1}k_{a2}...k_{an} }
|
|
174
|
+
|
|
175
|
+
Where :math: '\term_n' refers to the nth term in the denominator, starting from 0
|
|
263
176
|
|
|
177
|
+
References:
|
|
178
|
+
Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 127-130. Wiley Interscience, 1996.
|
|
179
|
+
|
|
180
|
+
Examples:
|
|
181
|
+
>>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
|
|
182
|
+
0.999...
|
|
183
|
+
|
|
184
|
+
The sum of all alpha values should equal 1
|
|
185
|
+
|
|
186
|
+
>>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
187
|
+
0.021...
|
|
188
|
+
>>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
189
|
+
0.979...
|
|
190
|
+
>>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
|
|
191
|
+
2.043...e-09
|
|
192
|
+
|
|
193
|
+
If pH is equal to one of the pKa values the function should return 0.5.
|
|
194
|
+
|
|
195
|
+
>>> alpha(1,6.35,[6.35,10.33])
|
|
196
|
+
0.5
|
|
264
197
|
"""
|
|
265
198
|
# generate an error if no pKa values are specified
|
|
266
199
|
if len(pKa_list) == 0:
|
|
267
|
-
|
|
268
|
-
return None
|
|
200
|
+
raise ValueError("No pKa values given. Cannot calculate distribution coefficient.")
|
|
269
201
|
|
|
270
202
|
# generate an error if n > number of pKa values
|
|
271
203
|
if len(pKa_list) < n:
|
|
272
|
-
|
|
273
|
-
"Insufficient number of pKa values given. Cannot calculate distribution coeffiicent."
|
|
274
|
-
)
|
|
275
|
-
return None
|
|
204
|
+
raise ValueError("Insufficient number of pKa values given. Cannot calculate distribution coefficient.")
|
|
276
205
|
|
|
277
|
-
#
|
|
278
|
-
|
|
206
|
+
# sort the pKa list
|
|
207
|
+
pKa_list = sorted(pKa_list)
|
|
279
208
|
|
|
280
209
|
# determine how many protons the acid has
|
|
281
210
|
num_protons = len(pKa_list)
|
|
282
211
|
|
|
283
212
|
# build a list of terms where the term subscript corresponds to the list index
|
|
284
|
-
terms_list = []
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
# add the term to the list
|
|
294
|
-
terms_list.append(k_term * Hplus ** (num_protons - item))
|
|
295
|
-
|
|
296
|
-
# build the expression
|
|
297
|
-
numerator = terms_list[n]
|
|
298
|
-
denominator = 0
|
|
299
|
-
for item in terms_list:
|
|
300
|
-
denominator += item
|
|
213
|
+
terms_list = [10 ** (-pH * num_protons)]
|
|
214
|
+
for i in range(len(pKa_list)):
|
|
215
|
+
# multiply together all K values with
|
|
216
|
+
k_term = 1
|
|
217
|
+
for pK in pKa_list[0 : i + 1]:
|
|
218
|
+
k_term *= 10**-pK
|
|
219
|
+
terms_list.append(k_term * 10 ** (-pH * (num_protons - (i + 1))))
|
|
220
|
+
print(terms_list)
|
|
301
221
|
|
|
302
222
|
# return the desired distribution factor
|
|
303
|
-
alpha =
|
|
304
|
-
logger.
|
|
223
|
+
alpha = terms_list[n] / sum(terms_list)
|
|
224
|
+
logger.debug(
|
|
305
225
|
"Calculated %s-deprotonated acid distribution coefficient of %s for pKa=%s at pH %s % n,alpha,pKa_list,pH"
|
|
306
226
|
)
|
|
307
227
|
return alpha
|