chempy.util package

This package collects utility functions used throughout the ChemPy package.

Submodules

chempy.util.arithmeticdict module

class chempy.util.arithmeticdict.ArithmeticDict[source]

Bases: collections.defaultdict

A dictionary which supports arithmetics

Subclassed from defaultdict, with support for addition, subtraction, multiplication and division. If other term/factor has a keys() method the arithmetics are performed on a key per key basis. If keys() is missing, the operation is broadcasted onto all values. Nonexisting keys are interpreted to signal a zero.

Notes

__eq__ ignores values equal to self.default_factory()

Examples

>>> d1 = ArithmeticDict(float, {'a': 2.0, 'b': 3.0})
>>> d2 = ArithmeticDict(float, {'b': 5.0, 'c': 7.0})
>>> (d1 + d2) == {'a': 2., 'b': 8., 'c': 7., 'd': 0.}
True
>>> (d1 * d1) == {'a': 4.0, 'b': 9.0, 'z': 0}
True
>>> (d1 * d2) == {'b': 15}
True
>>> d1*2 == {'a': 4, 'b': 6}
True
>>> (d1 / {'a': 2, 'b': 11})['b'] == 3./11
True
>>> d2/3 == {'b': 5./3, 'c': 7./3}
True

Methods

all_non_negative()
clear(() -> None.  Remove all items from D.)
copy()
fromkeys(...) v defaults to None.
get((k[,d]) -> D[k] if k in D, ...)
has_key((k) -> True if D has a key k, else False)
isclose(other[, rtol, atol])
items(() -> list of D’s (key, value) pairs, ...)
iteritems(() -> an iterator over the (key, ...)
iterkeys(() -> an iterator over the keys of D)
itervalues(...)
keys(() -> list of D’s keys)
pop((k[,d]) -> v, ...) If key is not found, d is returned if given, otherwise KeyError is raised
popitem(() -> (k, v), ...) 2-tuple; but raise KeyError if D is empty.
setdefault((k[,d]) -> D.get(k,d), ...)
update(([E, ...) If E present and has a .keys() method, does: for k in E: D[k] = E[k]
values(() -> list of D’s values)
viewitems(...)
viewkeys(...)
viewvalues(...)
all_non_negative()[source]
copy()[source]
isclose(other, rtol=1e-12, atol=None)[source]

chempy.util.bkh module

Utilities for plotting with bokeh.

chempy.util.bkh.integration_with_sliders(rsys, tend, c0, parameters, fig_kwargs=None, unit_registry=None, output_conc_unit=None, output_time_unit=None, slider_kwargs=None, x_axis_type='linear', y_axis_type='linear', integrate_kwargs=None, substitutions=None)[source]

chempy.util.deprecation module

class chempy.util.deprecation.Deprecation(last_supported_version=None, will_be_missing_in=None, use_instead=None, issue=None, issues_url=None, warning=<type 'exceptions.DeprecationWarning'>)[source]

Bases: object

Decorator factory for deprecating functions or classes.

This class represent deprecations of functions or classes and is designed to be used with the warnings library.

Parameters:

last_supported_version : str, optional

Version string, e.g. '0.2.1'.

will_be_missing_in : str, optional

Version string, e.g. '0.3.0'.

use_instead : object or str, optional

Function or class to use instead or descriptive string.

issue : str, optional

issues_url : callback, optional

Converts issue to url, e.g. lambda s: 'https://github.com/user/repo/issues/%s/' % s.lstrip('gh-').

warning: DeprecationWarning, optional

Any subclass of DeprecationWarning, tip: you may invoke: warnings.simplefilter('once', MyWarning) at module init.

Notes

DeprecationWarning is ignored by default. Use custom warning and filter appropriately. Alternatively, run python with -W flag or set the appropriate environment variable:

$ python -c 'import warnings as w; w.warn("X", DeprecationWarning)'
$ python -Wd -c 'import warnings as w; w.warn("X", DeprecationWarning)'
-c:1: DeprecationWarning: X
$ export PYTHONWARNINGS=d
$ python -c 'import warnings as w; w.warn("X", DeprecationWarning)'
-c:1: DeprecationWarning: X

Examples

>>> import warnings
>>> warnings.simplefilter("error", DeprecationWarning)
>>> @Deprecation()
... def f():
...     return 1
...
>>> f()  
Traceback (most recent call last):
...
DeprecationWarning: f is deprecated.
>>> @Deprecation(last_supported_version='0.4.0')
... def some_old_function(x):
...     return x*x - x
...
>>> Deprecation.inspect(some_old_function).last_supported_version
'0.4.0'
>>> @Deprecation(will_be_missing_in='1.0')
... class ClumsyClass(object):
...     pass
...
>>> Deprecation.inspect(ClumsyClass).will_be_missing_in
'1.0'
>>> warnings.resetwarnings()

Methods

__call__(wrapped) Decorates function to be deprecated
inspect(obj) Get the Deprecation instance of a deprecated function.
classmethod inspect(obj)[source]

Get the Deprecation instance of a deprecated function.

chempy.util.graph module

Convenince functions for representing reaction systems as graphs.

chempy.util.graph.rsys2dot(rsys, tex=False, rprefix='r', rref0=1, nodeparams='[label="{}" shape=diamond]', colors=('maroon', 'darkgreen'))[source]

Returns list of lines of DOT (graph description language) formated graph.

Parameters:

rsys: ReactionSystem

tex: bool (default False)

If set True, output will be LaTeX formated

(Substance need to have latex_name attribute set)

rprefix: string

Reaction enumeration prefix, default: r

rref0: integer

Reaction enumeration inital counter value, default: 1

nodeparams: string

DOT formated param list, default: [label={} shape=diamond]

Returns:

list of lines of DOT representation of the graph representation.

chempy.util.graph.rsys2graph(rsys, fname, output_dir=None, prog=None, save=False, **kwargs)[source]

Convenience function to call rsys2dot and write output to file and render the graph

Parameters:

rsys: ReactionSystem

fname: str

filename

output_dir: str (optional)

path to directory (default: temporary directory)

prog: str (optional)

default: ‘dot’

save: bool

removes temporary directory if False, default: False

**kwargs:

parameters to pass along to rsys2dot

Returns:

str

Outpath

Examples

>>> rsys2graph(rsys, sbstncs, '/tmp/out.png')  

chempy.util.parsing module

Functions for chemical formulae and reactions

chempy.util.parsing.atomic_number(name)[source]
chempy.util.parsing.formula_to_composition(formula, prefixes=None, suffixes=('(s)', '(l)', '(g)', '(aq)'))[source]

Parse composition of formula representing a chemical formula

Composition is represented as a dict mapping int -> int (atomic number -> multiplicity). “Atomic number” 0 represents net charge.

Parameters:

formula: str

Chemical formula, e.g. ‘H2O’, ‘Fe+3’, ‘Cl-‘

prefixes: iterable strings

Prefixes to ignore, e.g. (‘.’, ‘alpha-‘)

suffixes: tuple of strings

Suffixes to ignore, e.g. (‘(g)’, ‘(s)’)

Examples

>>> formula_to_composition('NH4+') == {0: 1, 1: 4, 7: 1}
True
>>> formula_to_composition('.NHO-(aq)') == {0: -1, 1: 1, 7: 1, 8: 1}
True
>>> formula_to_composition('Na2CO3.7H2O') == {11: 2, 6: 1, 8: 10, 1: 14}
True
chempy.util.parsing.formula_to_html(formula, prefixes=None, infixes=None, **kwargs)[source]

Convert formula string to html string representation

Parameters:

formula : str

Chemical formula, e.g. ‘H2O’, ‘Fe+3’, ‘Cl-‘

prefixes : dict

Prefix transformations, default: greek letters and .

infixes : dict

Infix transformations, default: .

suffixes : tuple of strings

Suffixes to keep, e.g. (‘(g)’, ‘(s)’)

Examples

>>> formula_to_html('NH4+')
'NH<sub>4</sub><sup>+</sup>'
>>> formula_to_html('Fe(CN)6+2')
'Fe(CN)<sub>6</sub><sup>2+</sup>'
>>> formula_to_html('Fe(CN)6+2(aq)')
'Fe(CN)<sub>6</sub><sup>2+</sup>(aq)'
>>> formula_to_html('.NHO-(aq)')
'&sdot;NHO<sup>-</sup>(aq)'
>>> formula_to_html('alpha-FeOOH(s)')
'&alpha;-FeOOH(s)'
chempy.util.parsing.formula_to_latex(formula, prefixes=None, infixes=None, **kwargs)[source]

Convert formula string to latex representation

Parameters:

formula: str

Chemical formula, e.g. ‘H2O’, ‘Fe+3’, ‘Cl-‘

prefixes: dict

Prefix transofmrations, default: greek letters and .

infixes: dict

Infix transformations, default: .

suffixes: iterable of str

What suffixes not to interpret, default: (s), (l), (g), (aq)

Examples

>>> formula_to_latex('NH4+')
'NH_{4}^{+}'
>>> formula_to_latex('Fe(CN)6+2')
'Fe(CN)_{6}^{2+}'
>>> formula_to_latex('Fe(CN)6+2(aq)')
'Fe(CN)_{6}^{2+}(aq)'
>>> formula_to_latex('.NHO-(aq)')
'^\\bullet NHO^{-}(aq)'
>>> formula_to_latex('alpha-FeOOH(s)')
'\\alpha-FeOOH(s)'
chempy.util.parsing.formula_to_unicode(formula, prefixes=None, infixes=None, **kwargs)[source]

Convert formula string to unicode string representation

Parameters:

formula : str

Chemical formula, e.g. ‘H2O’, ‘Fe+3’, ‘Cl-‘

prefixes : dict

Prefix transofmrations, default: greek letters and .

infixes : dict

Infix transofmrations, default: .

suffixes : tuple of strings

Suffixes to keep, e.g. (‘(g)’, ‘(s)’)

Examples

>>> formula_to_unicode('NH4+') == u'NH₄⁺'
True
>>> formula_to_unicode('Fe(CN)6+2') == u'Fe(CN)₆²⁺'
True
>>> formula_to_unicode('Fe(CN)6+2(aq)') == u'Fe(CN)₆²⁺(aq)'
True
>>> formula_to_unicode('.NHO-(aq)') == u'⋅NHO⁻(aq)'
True
>>> formula_to_unicode('alpha-FeOOH(s)') == u'α-FeOOH(s)'
True
chempy.util.parsing.mass_from_composition(composition)[source]

Calculates molecular mass from atomic weights

Parameters:

composition: dict

Dictionary mapping int (atomic number) to int (coefficient)

Returns:

float

molecular weight in atomic mass units

Notes

Atomic number 0 denotes charge or “net electron defficiency”

Examples

>>> '%.2f' % mass_from_composition({0: -1, 1: 1, 8: 1})
'17.01'
chempy.util.parsing.number_to_scientific_html(number, fmt='%.3g')[source]

Examples

>>> number_to_scientific_html(3.14) == '3.14'
True
>>> number_to_scientific_html(3.14159265e-7)
'3.14&sdot;10<sup>-7</sup>'
>>> import quantities as pq
>>> number_to_scientific_html(2**0.5 * pq.m / pq.s)
'1.41 m/s'
chempy.util.parsing.number_to_scientific_latex(number, fmt='%.3g')[source]

Examples

>>> number_to_scientific_latex(3.14) == '3.14'
True
>>> number_to_scientific_latex(3.14159265e-7)
'3.14\\cdot 10^{-7}'
>>> import quantities as pq
>>> number_to_scientific_latex(2**0.5 * pq.m / pq.s)
'1.41 \\mathrm{\\frac{m}{s}}'
chempy.util.parsing.number_to_scientific_unicode(number, fmt='%.3g')[source]

Examples

>>> number_to_scientific_unicode(3.14) == u'3.14'
True
>>> number_to_scientific_unicode(3.14159265e-7) == u'3.14·10⁻⁷'
True
>>> import quantities as pq
>>> number_to_scientific_html(2**0.5 * pq.m / pq.s)
'1.41 m/s'
chempy.util.parsing.to_reaction(line, substance_keys, token, Cls, globals_=None, **kwargs)[source]

Parses a string into a Reaction object and substances

Reac1 + 2 Reac2 + (2 Reac1) -> Prod1 + Prod2; 10**3.7; ref=’doi:12/ab’ Reac1 = Prod1; 2.1;

Parameters:

line: str

string representation to be parsed

substance_keys: iterable of strings

Allowed names, e.g. (‘H2O’, ‘H+’, ‘OH-‘)

token : str

delimiter token between reactant and product side

Cls : class

e.g. subclass of Reaction

globals_: dict (optional)

Globals passed on to eval(), when None: chempy.units.default_units is used with ‘chempy’ and ‘default_units’ extra entries.

Notes

This function calls eval(), hence there are severe security concerns with running this on untrusted data.

chempy.util.pyutil module

General utilities and exceptions.

exception chempy.util.pyutil.ChemPyDeprecationWarning[source]

Bases: exceptions.DeprecationWarning

exception chempy.util.pyutil.NoConvergence[source]

Bases: exceptions.Exception

class chempy.util.pyutil.defaultkeydict[source]

Bases: collections.defaultdict

defaultdict where default_factory should have the signature key -> value

Examples

>>> d = defaultkeydict(lambda k: '[%s]' % k, {'a': '[a]', 'b': '[B]'})
>>> d['a']
'[a]'
>>> d['b']
'[B]'
>>> d['c']
'[c]'

Methods

clear(() -> None.  Remove all items from D.)
copy(() -> a shallow copy of D.)
fromkeys(...) v defaults to None.
get((k[,d]) -> D[k] if k in D, ...)
has_key((k) -> True if D has a key k, else False)
items(() -> list of D’s (key, value) pairs, ...)
iteritems(() -> an iterator over the (key, ...)
iterkeys(() -> an iterator over the keys of D)
itervalues(...)
keys(() -> list of D’s keys)
pop((k[,d]) -> v, ...) If key is not found, d is returned if given, otherwise KeyError is raised
popitem(() -> (k, v), ...) 2-tuple; but raise KeyError if D is empty.
setdefault((k[,d]) -> D.get(k,d), ...)
update(([E, ...) If E present and has a .keys() method, does: for k in E: D[k] = E[k]
values(() -> list of D’s values)
viewitems(...)
viewkeys(...)
viewvalues(...)
chempy.util.pyutil.defaultnamedtuple(typename, field_names, defaults=())[source]

Generates a new subclass of tuple with default values.

Parameters:

typename : string

The name of the class.

field_names : str or iterable

An iterable of splitable string.

defaults : iterable

Default values for field_names, counting [-len(defaults):].

Returns:

A new tuple subclass named typename

Examples

>>> Body = defaultnamedtuple('Body', 'x y z density', (1.0,))
>>> Body.__doc__
'Body(x, y, z, density)'
>>> b = Body(10, z=3, y=5)
>>> b._asdict()
OrderedDict([('x', 10), ('y', 5), ('z', 3), ('density', 1.0)])
chempy.util.pyutil.deprecated(*args, **kwargs)[source]

Helper to Deprecation for using ChemPyDeprecationWarning.

chempy.util.pyutil.memoize(nargs=0)[source]

chempy.util.regression module

chempy.util.regression.avg_params(opt_params, cov_params, label_cb=None, plot=False)[source]
chempy.util.regression.irls(x, y, w_cb=<function <lambda>>, itermax=16, rmsdwtol=1e-08, full_output=False)[source]

Iteratively reweighted least squares

Parameters:

x : array_like

y : array_like

w_cb : callbable

signature (x, y, beta, cov) -> weight

itermax : int

rmsdwtol : float

full_output : bool

Returns:

beta : length-2 array

parameters

cov : 2x2 array

variance-covariance matrix

info : dict

if full_output == True, keys:
  • weights
  • niter
chempy.util.regression.least_squares(x, y, w=1)[source]

Least-squares (w or w/o weights) fit to data series.

Linear regression (unweighted or weighted).

Parameters:

x : array_like

y : array_like

w : array_like, optional

Returns:

length 2 tuple : pair of parameter estimates (intercept and slope)

2x2 array : variance-covariance matrix

float : R-squared (goodness of fit)

References

Wikipedia & standard texts on least sqaures method. Comment regarding R2 in WLS:

Willett, John B., and Judith D. Singer. “Another cautionary note about R 2: Its use in weighted least-squares regression analysis.” The American Statistician 42.3 (1988): 236-238.

Examples

>>> beta, vcv, R2 = least_squares([0, 1, 2], [1, 3, 5])
>>> all(abs(beta - [1, 2]) < 1e-14), R2 == 1, (abs(vcv) < 1e-14).all()
(True, True, True)
>>> b1, v1, r2_1 = least_squares([1, 2, 3], [0, 1, 4], [1, 1, 1])
>>> b2, v2, r2_2 = least_squares([1, 2, 3], [0, 1, 4], [1, 1, .2])
>>> abs(b2[1] - 1) < abs(b1[1] - 1)
True
chempy.util.regression.plot_fit(x, y, beta, kw_data=None, kw_fit=None)[source]

chempy.util.stoich module

Utility functions related to stoichiometry.

chempy.util.stoich.decompose_yields(yields, rxns, atol=1e-10)[source]

Decomposes yields into mass-action reactions

This function offers a way to express a reaction with non-integer stoichiometric coefficients as a linear combination of production reactions with integer coefficients.

Ak = y

A is (n_species x n_reactions) matrix, k is “rate coefficient”, y is yields

Parameters:

yields: OrderedDict

specie names as keys and yields as values

rxns: iterable :class:`Reaction` instances

dict keys must match those of yields each pair of dictionaries gives stoichiometry (1st is reactant, 2nd is products)

atol: float

absolute tolerance for residuals

Returns:

1-dimensional array of effective rate coefficients.

Raises:

ValueError

When atol is exceeded

numpy.LinAlgError

When numpy.linalg.lstsq fails to converge

Examples

>>> from chempy import Reaction
>>> h2a = Reaction({'H2O': 1}, {'H2': 1, 'O': 1})
>>> h2b = Reaction({'H2O': 1}, {'H2': 1, 'H2O2': 1}, inact_reac={'H2O': 1})
>>> decompose_yields({'H2': 3, 'O': 2, 'H2O2': 1}, [h2a, h2b])
array([ 2.,  1.])
chempy.util.stoich.get_coeff_mtx(substances, stoichs)[source]

Create a net stoichiometry matrix from reactions described by pairs of dictionaries.

Parameters:

substances: sequence of keys in stoichs dict pairs

stoichs: sequence of pairs of dicts

pairs of reactant and product dicts mapping substance keys to stoichiometric coefficients (integers)

Returns:

2 dimensional array of shape (len(substances), len(stoichs))

chempy.util.table module

Convenience functions for presenting reaction systems in tables.

chempy.util.table.render_tex_to_pdf(contents, texfname, pdffname, output_dir, save)[source]

Generates a pdf from a tex file by calling pdflatex

Parameters:

contents : str

texfname : path

pdffname : path

output_dir : path

save : path or bool or str(bool)

chempy.util.table.rsys2pdf_table(rsys, output_dir=None, doc_template=None, doc_template_dict=None, save=True, landscape=False, **kwargs)[source]

Convenience function to render a ReactionSystem as e.g. a pdf using e.g. pdflatex.

Parameters:

rsys : ReactionSystem

output_dir : path to output directory

(default: system’s temporary folder)

doc_template : string

LaTeX boiler plate temlpate including preamble, document environment etc.

doc_template_dict : dict (string -> string)

dict used to render temlpate (excl. ‘table’)

longtable : bool

use longtable in defaults. (default: False)

**kwargs :

passed on to rsys2table

chempy.util.table.rsys2table(rsys, table_template=None, table_template_dict=None, param_name='Rate constant', **kwargs)[source]

Renders user provided table_template with table_template_dict which also has ‘body’ entry generated from rsys2tablines.

Defaults is LaTeX table requiring booktabs package to be used (add usepackage{booktabs} to preamble).

Parameters:

rsys : ReactionSystem

table_template : string

table_tempalte_dict : dict used to render table_template (excl. “body”)

param_name : str

Column header for parameter column

longtable : bool

use longtable in defaults. (default: False)

**kwargs :

passed onto rsys2tablines

chempy.util.table.rsys2tablines(rsys, rref0=1, coldelim=' & ', tex=True, ref_fmt=None, unit_registry=None, unit_fmt='{}', k_fmt='%.4g')[source]

Generates a table representation of a ReactionSystem.

Parameters:

rsys : ReactionSystem

rref0 : integer

default start of index counter (default: 1)

coldelim : string

column delimiter (default: ‘ & ‘)

tex : bool

use latex formated output (default: True)

ref_fmt : string or callable

format string of ref attribute of reactions

unit_registry : unit registry

optional (default: None)

chempy.util.testing module

class chempy.util.testing.requires(*reqs)[source]

Bases: object

Conditional skipping (on requirements) of tests in pytest

Examples

>>> @requires('numpy')
... def test_sqrt():
...     import numpy as np
...     assert np.sqrt(4) == 2
...
>>> @requires('numpy>=1.9.0')
... def test_nanmedian():
...     import numpy as np
...     a = np.array([[10.0, 7, 4], [3, 2, 1]])
...     a[0, 1] = np.nan
...     assert np.nanmedian(a) == 3
...

Methods

__call__(cb)