In [1]:
# Setup
from __future__ import print_function, absolute_import, division
import ionize
import pprint
from matplotlib import pyplot as plot
%matplotlib inline
import numpy as np
np.set_printoptions(precision=3)
The basic building block that ionize is the a single ionic species. Small ions (as opposed to ion complexes or polyions) are represented by the Ion class.
An Ion has the following properties that can be set on initialization.
Only the name, valence, pKa, and mobility are required parameters. All other parameters are optional.
In [2]:
acid = ionize.Ion('myAcid', [-1], [5], [-25e-9])
base = ionize.Ion('myBase', [1], [8], [20e-9])
print(acid) # The string includes only the class and name.
print(repr(base)) # The representation contains enough information to reconstruct the ion.
The guranteed interfaces of ion species are:
In addition, BaseIon subclasses usually have some unique interfaced.
In [3]:
print('myAcid Ka at (I=0 M) =', acid.acidity())
print('myAcid Ka at (I=0.5 M) =', acid.acidity(ionic_strength=0.5))
pH = np.linspace(0,14)
for I in [None, 0., 0.001, 0.01, 0.1]:
mu = [base.mobility(p, I) for p in pH]
if I is not None:
label = 'I={} M'.format(I)
else:
label = 'I=None'
plot.plot(pH, mu, label=label)
plot.xlabel('pH'); plot.xlim(0, 14)
plot.ylabel('effective mobility (m^2/v/s)'); plot.ylim(-.1e-8, 2.1e-8)
plot.legend()
plot.show()
Note the difference between ionic_strength parameters here. If ionic_strength is 0, the numerical value of 0 is used in each calculation. However, it is impossible to have a solution of pH 0 with ionic_strength of 0.
When the default value of None is used for ionic_strength, ionize uses the minimum ionic strength at the selected pH.
In [4]:
db = ionize.Database()
histidine = db['histidine']
print(repr(histidine))
for ionic_strength in (None, 0):
mu_histidine = [histidine.mobility(p, ionic_strength=ionic_strength) for p in pH]
plot.plot(pH, mu_histidine, label="I={}".format(ionic_strength))
plot.xlabel('pH'); plot.xlim([0, 14])
plot.ylabel('effective mobility (m^2/v/s)')
plot.legend()
plot.show()
In [5]:
print("Search results for 'amino'\n--------------------------")
pprint.pprint(db.search('amino'))
print("\nSearch results for 'chloric'\n----------------------------")
pprint.pprint(db.search('chloric'))
print("\nSearch results for 'per'\n------------------------")
pprint.pprint(db.search('per'))
print('\nOh, copper is what I was looking for.')
print(db.load('copper'))
In [6]:
print(len(db.data), 'ions in database.')
Getting the properties of a single ionic species in solution is useful, but the real challenge of dealing with aqueous solutions of ions is finding properties based on the equilibrium state of multiple ionic species. ionize can perform those calculations using the Solution class. Solution objects are initialized using ionize.Solution(ions, concentrations), where ions is a list of Ion objects and concentration is a list concentrations of the ions, with concentrations in molar.
In [7]:
buffer=ionize.Solution([db['tris'], db['chloride']], [0.1, 0.085])
print('pH =', buffer.pH)
print('I =', buffer.ionic_strength, 'M')
print('conductivity =', buffer.conductivity(), 'S/m')
print('buffering capacity =', buffer.buffering_capacity(), 'M')
print('debye length =', buffer.debye(), 'm')
Solutions can be initialized with ion names instead of ion objects.
In [8]:
sol = ionize.Solution(['bis-tris', 'acetic acid'], [0.1, 0.03])
print([ion.name for ion in sol.ions])
print(sol.concentration('acetic acid'))
We can iterate through solutions to calculate the pH of a titration between two ions.
In [9]:
c_tris = 0.1
c_hcl = np.linspace(0.0, 0.2, 50)
t_pH = [ionize.Solution(['tris', 'hydrochloric acid'], [c_tris, c_h]).pH for c_h in c_hcl]
plot.plot(c_hcl/c_tris, t_pH)
plot.xlabel('[HCl]/[Tris]')
plot.ylabel('pH')
plot.show()
A Solution can also be initialized without ions, e.g. as water.
In [ ]:
water = ionize.Solution()
print('I =', water.ionic_strength, 'M')
print('pH =', water.pH)
print('conductivity =', water.conductivity(), 'S/m')
A Solution can also be added and multiplied. This can be useful when calculating the results of diltuions, as below.
In [ ]:
print('Stock:', buffer)
dilution = 0.5 * buffer + 0.5 * water
print('Dilution:', dilution)
Solutions can be titrated to a specified pH. To do so, make a solution, and then specify a titrant, a property, and a target.
In [ ]:
buff = ionize.Solution(['tris'], 0.1)
print(buff.titrate('hydrochloric acid', 8.2))
print(buff.titrate('hydrochloric acid', 3))
print(buff.conductivity())
print(repr(buff.titrate('hydrochloric acid', 3, titration_property = 'conductivity')))
print(repr(buff.titrate('hydrochloric acid', 8)))
In [ ]: