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/database.py
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module contains classes, functions, and methods for reading input files
|
|
3
|
-
and assembling database entries for use by pyEQL.
|
|
4
|
-
|
|
5
|
-
By default, pyEQL searches all files in the /database subdirectory for parameters.
|
|
6
|
-
|
|
7
|
-
:copyright: 2013-2020 by Ryan S. Kingsbury
|
|
8
|
-
:license: LGPL, see LICENSE for more details.
|
|
9
|
-
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
# logging system
|
|
13
|
-
import logging
|
|
14
|
-
|
|
15
|
-
# add a filter to emit only unique log messages to the handler
|
|
16
|
-
from pyEQL.logging_system import Unique
|
|
17
|
-
|
|
18
|
-
# for parameter creation functions
|
|
19
|
-
import pyEQL.parameter as pm
|
|
20
|
-
|
|
21
|
-
# for file input/output functions
|
|
22
|
-
import os
|
|
23
|
-
|
|
24
|
-
logger = logging.getLogger(__name__)
|
|
25
|
-
unique = Unique()
|
|
26
|
-
logger.addFilter(unique)
|
|
27
|
-
|
|
28
|
-
# add a handler for console output, since pyEQL is meant to be used interactively
|
|
29
|
-
ch = logging.StreamHandler()
|
|
30
|
-
|
|
31
|
-
# create formatter for the log
|
|
32
|
-
formatter = logging.Formatter("(%(name)s) - %(levelname)s - %(message)s")
|
|
33
|
-
|
|
34
|
-
# add formatter to the handler
|
|
35
|
-
ch.setFormatter(formatter)
|
|
36
|
-
logger.addHandler(ch)
|
|
37
|
-
|
|
38
|
-
# Database Management Functions
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class Paramsdb:
|
|
42
|
-
"""
|
|
43
|
-
create a global dictionary to contain a dynamically-generated list of Parameters
|
|
44
|
-
for solute species. The dictionary keys are the individual chemical species
|
|
45
|
-
formulas. The dictionary's values are a python set object containing all parameters
|
|
46
|
-
that apply to the species.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
def __init__(self):
|
|
50
|
-
|
|
51
|
-
self.parameters_database = {}
|
|
52
|
-
|
|
53
|
-
# set the directory containing database files
|
|
54
|
-
self.database_dir = [os.path.dirname(__file__) + "/database"]
|
|
55
|
-
|
|
56
|
-
def add_path(self, path):
|
|
57
|
-
"""
|
|
58
|
-
Add a user-defined directory to the database search path
|
|
59
|
-
"""
|
|
60
|
-
self.database_dir.append(path)
|
|
61
|
-
|
|
62
|
-
def list_path(self):
|
|
63
|
-
"""
|
|
64
|
-
List all search paths for database files
|
|
65
|
-
"""
|
|
66
|
-
for path in self.database_dir:
|
|
67
|
-
print(path)
|
|
68
|
-
|
|
69
|
-
def search_parameters(self, formula):
|
|
70
|
-
"""Each time a new solute species is created in a solution, this function:
|
|
71
|
-
|
|
72
|
-
1) searches to see whether a list of parameters for the species has already been
|
|
73
|
-
compiled from the database
|
|
74
|
-
2) searches all files in the specified database directory(ies) for the species
|
|
75
|
-
3) creates a Parameter object for each value found
|
|
76
|
-
4) compiles these objects into a set
|
|
77
|
-
5) adds the set to a dictionary indexed by species name (formula)
|
|
78
|
-
6) points the new solute object to the dictionary
|
|
79
|
-
|
|
80
|
-
formula : str
|
|
81
|
-
String representing the chemical formula of the species.
|
|
82
|
-
"""
|
|
83
|
-
# get the hill_order() and is_valid_formula() methods from the chemistry module
|
|
84
|
-
import pyEQL.chemical_formula as chem
|
|
85
|
-
|
|
86
|
-
# if the formula is already in the database, then we've already searched
|
|
87
|
-
# and compiled parameters, so there is no need to do it again.
|
|
88
|
-
if formula in self.parameters_database:
|
|
89
|
-
pass
|
|
90
|
-
else:
|
|
91
|
-
# add an entry to the parameters database
|
|
92
|
-
self.parameters_database[formula] = set()
|
|
93
|
-
|
|
94
|
-
# search all the files in each database directory
|
|
95
|
-
for directory in self.database_dir:
|
|
96
|
-
for file in os.listdir(directory):
|
|
97
|
-
# reset the line number count
|
|
98
|
-
line_num = 0
|
|
99
|
-
|
|
100
|
-
# ignore the template file
|
|
101
|
-
if file == "template.tsv":
|
|
102
|
-
continue
|
|
103
|
-
|
|
104
|
-
# look at only .csv files
|
|
105
|
-
if ".tsv" in file:
|
|
106
|
-
|
|
107
|
-
# open each file
|
|
108
|
-
current_file = open(directory + "/" + file, "r")
|
|
109
|
-
|
|
110
|
-
# read each line of the file, looking for the formula
|
|
111
|
-
try:
|
|
112
|
-
for line in current_file:
|
|
113
|
-
|
|
114
|
-
line_num += 1
|
|
115
|
-
|
|
116
|
-
try:
|
|
117
|
-
# look for keywords in the first column of each file. If found,
|
|
118
|
-
# store the entry from the 2nd column
|
|
119
|
-
if "Name" in line:
|
|
120
|
-
param_name = _parse_line(line)[1]
|
|
121
|
-
|
|
122
|
-
elif "Description" in line:
|
|
123
|
-
param_desc = _parse_line(line)[1]
|
|
124
|
-
|
|
125
|
-
elif "Unit" in line:
|
|
126
|
-
param_unit = _parse_line(line)[1]
|
|
127
|
-
|
|
128
|
-
elif "Reference" in line:
|
|
129
|
-
param_ref = _parse_line(line)[1]
|
|
130
|
-
|
|
131
|
-
elif "Temperature" in line:
|
|
132
|
-
param_temp = _parse_line(line)[1]
|
|
133
|
-
|
|
134
|
-
elif "Pressure" in line:
|
|
135
|
-
param_press = _parse_line(line)[1]
|
|
136
|
-
|
|
137
|
-
elif "Ionic Strength" in line:
|
|
138
|
-
param_ionic = _parse_line(line)[1]
|
|
139
|
-
|
|
140
|
-
elif "Comment" in line:
|
|
141
|
-
param_comment = _parse_line(line)[1]
|
|
142
|
-
|
|
143
|
-
# use the hill_order() function to standardize the
|
|
144
|
-
# supplied formula. Then standardize teh formulas in the
|
|
145
|
-
# database and see if they match.
|
|
146
|
-
# this allows a database entry for 'MgCl2' to be matched
|
|
147
|
-
# even if the user enters 'Mg(Cl)2', for example
|
|
148
|
-
elif chem.is_valid_formula(_parse_line(line)[0]):
|
|
149
|
-
if chem.hill_order(formula) == chem.hill_order(
|
|
150
|
-
_parse_line(line)[0]
|
|
151
|
-
):
|
|
152
|
-
# if there are multiple columns, pass the values as a list.
|
|
153
|
-
# If a single column, then just pass the value
|
|
154
|
-
if len(_parse_line(line)) > 2:
|
|
155
|
-
param_value = _parse_line(line)[1:]
|
|
156
|
-
else:
|
|
157
|
-
param_value = _parse_line(line)[1]
|
|
158
|
-
|
|
159
|
-
# Create a new parameter object
|
|
160
|
-
parameter = pm.Parameter(
|
|
161
|
-
param_name,
|
|
162
|
-
param_value,
|
|
163
|
-
param_unit,
|
|
164
|
-
reference=param_ref,
|
|
165
|
-
pressure=param_press,
|
|
166
|
-
temperature=param_temp,
|
|
167
|
-
ionic_strength=param_ionic,
|
|
168
|
-
description=param_desc,
|
|
169
|
-
comment=param_comment,
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Add the parameter to the set for this species
|
|
173
|
-
self.parameters_database[formula].add(
|
|
174
|
-
parameter
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
except ValueError:
|
|
178
|
-
logger.warning(
|
|
179
|
-
"Error encountered when reading line %s in %s"
|
|
180
|
-
% (line_num, file)
|
|
181
|
-
)
|
|
182
|
-
continue
|
|
183
|
-
|
|
184
|
-
# log a warning if an invalid character prevents reading a line
|
|
185
|
-
except UnicodeDecodeError:
|
|
186
|
-
logger.warning(
|
|
187
|
-
"Invalid character found when reading %s. File skipped."
|
|
188
|
-
% file
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
current_file.close()
|
|
192
|
-
|
|
193
|
-
def has_parameter(self, formula, name):
|
|
194
|
-
"""
|
|
195
|
-
Boolean test to determine whether a parameter exists in the database for a given species
|
|
196
|
-
"""
|
|
197
|
-
# search the available database files if the species is not currently
|
|
198
|
-
# in the database
|
|
199
|
-
if self.has_species(formula) is False:
|
|
200
|
-
self.search_parameters(formula)
|
|
201
|
-
|
|
202
|
-
found = False
|
|
203
|
-
|
|
204
|
-
try:
|
|
205
|
-
for item in self.parameters_database[formula]:
|
|
206
|
-
if item.get_name() == name:
|
|
207
|
-
found = True
|
|
208
|
-
else:
|
|
209
|
-
continue
|
|
210
|
-
|
|
211
|
-
return found
|
|
212
|
-
|
|
213
|
-
except KeyError:
|
|
214
|
-
logger.error("Species %s not found in database" % formula)
|
|
215
|
-
return None
|
|
216
|
-
|
|
217
|
-
def get_parameter(self, formula, name):
|
|
218
|
-
"""
|
|
219
|
-
Retrieve a parameter from the database
|
|
220
|
-
"""
|
|
221
|
-
found = False
|
|
222
|
-
|
|
223
|
-
try:
|
|
224
|
-
for item in self.parameters_database[formula]:
|
|
225
|
-
if item.get_name() == name:
|
|
226
|
-
found = True
|
|
227
|
-
return item
|
|
228
|
-
|
|
229
|
-
if not found:
|
|
230
|
-
logger.error(
|
|
231
|
-
"Parameter %s for species %s not found in database"
|
|
232
|
-
% (name, formula)
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
except KeyError:
|
|
236
|
-
logger.error("Species %s not found in database" % formula)
|
|
237
|
-
return None
|
|
238
|
-
|
|
239
|
-
def add_parameter(self, formula, parameter):
|
|
240
|
-
"""
|
|
241
|
-
Add a parameter to the database
|
|
242
|
-
"""
|
|
243
|
-
self.parameters_database[formula].add(parameter)
|
|
244
|
-
|
|
245
|
-
def has_species(self, formula):
|
|
246
|
-
"""
|
|
247
|
-
Boolean test to determine whether a species is present in the database
|
|
248
|
-
"""
|
|
249
|
-
if formula in self.parameters_database:
|
|
250
|
-
return True
|
|
251
|
-
else:
|
|
252
|
-
return False
|
|
253
|
-
|
|
254
|
-
def print_database(self, solute=None):
|
|
255
|
-
""" Function to generate a human-friendly summary of all the database parameters
|
|
256
|
-
that are actually used in the simulation
|
|
257
|
-
|
|
258
|
-
Parameters
|
|
259
|
-
----------
|
|
260
|
-
solute : str, optional
|
|
261
|
-
The chemical formula for a species. If this argument of supplied, the output
|
|
262
|
-
will contain only the database entries for this species. Otherwise,
|
|
263
|
-
all database entries will be printed.
|
|
264
|
-
|
|
265
|
-
"""
|
|
266
|
-
if solute is not None:
|
|
267
|
-
try:
|
|
268
|
-
key = solute
|
|
269
|
-
print("Parameters for species %s:" % key)
|
|
270
|
-
print("--------------------------\n")
|
|
271
|
-
for item in self.parameters_database[key]:
|
|
272
|
-
print(item)
|
|
273
|
-
except KeyError:
|
|
274
|
-
print("Species %s not found in database." % solute)
|
|
275
|
-
else:
|
|
276
|
-
for key in self.parameters_database.keys():
|
|
277
|
-
print("Parameters for species %s:" % key)
|
|
278
|
-
print("--------------------------\n")
|
|
279
|
-
for item in self.parameters_database[key]:
|
|
280
|
-
print(item)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def _parse_line(line):
|
|
284
|
-
"""
|
|
285
|
-
Function to parse lines in a tab-seprated value file format.
|
|
286
|
-
|
|
287
|
-
This function accepts a string (a line read from a tab-separated
|
|
288
|
-
input file). It removes the newline character and splits the string
|
|
289
|
-
at each tab stop, returning a list of the remaining substrings in which each
|
|
290
|
-
list entry corresponds to the contents of one cell in the file.
|
|
291
|
-
|
|
292
|
-
"""
|
|
293
|
-
# remove the newline character
|
|
294
|
-
line = line.replace("\n", "")
|
|
295
|
-
|
|
296
|
-
# separate the string at every tab stop
|
|
297
|
-
str_list = line.split("\t")
|
|
298
|
-
|
|
299
|
-
# return the list of string entries
|
|
300
|
-
return str_list
|