chemsynthcalc package

Submodules

chemsynthcalc.chem_errors module

Module that contains custom errors for use in ChemSynthCalc

exception chemsynthcalc.chem_errors.NoSuchAtom

Bases: Exception

Found atom(s) that are not in the periodic table.

exception chemsynthcalc.chem_errors.InvalidCharacter

Bases: Exception

Found some characters that do not belong in the chemical formula or reaction.

exception chemsynthcalc.chem_errors.MoreThanOneAdduct

Bases: Exception

There is more than one adduct (*).

exception chemsynthcalc.chem_errors.BracketsNotPaired

Bases: Exception

Some brackets do not come in pairs.

exception chemsynthcalc.chem_errors.NoSuchMode

Bases: Exception

Invalid calculation mode detected.

exception chemsynthcalc.chem_errors.NoSuchAlgorithm

Bases: Exception

Invalid calculation algorithm detected.

exception chemsynthcalc.chem_errors.NoSeparator

Bases: Exception

No separator was found in the reaction string.

exception chemsynthcalc.chem_errors.ReactionNotBalanced

Bases: Exception

This reaction is not balanced.

exception chemsynthcalc.chem_errors.ReactantProductDifference

Bases: Exception

The elements in reaction are not evenly distributed in reactants and products: some of atoms are only in one part of reaction.

exception chemsynthcalc.chem_errors.BadCoeffiecients

Bases: Exception

The coefficients are not not compliant (they have no physical meaning).

chemsynthcalc.chem_output module

class chemsynthcalc.chem_output.FormulaOutput(chemical_formula_output: dict)

Bases: object

Outputs for chemsynthcalc.chemical_formula.ChemicalFormula

A collection of methods for outputing results of chemsynthcalc.chemical_formula.ChemicalFormula. Default filenames of output files are "CSC_formula" with formula and nanosecond since the epoch.

Parameters

chemical_formula_output (dict) -- output of chemsynthcalc.chemical_formula.ChemicalFormula

print_results(print_rounding_order: int) None

Print results in the terminal.

Parameters

print_rounding_order (int) -- print precision

Returns

None

export_to_txt(filename: str, print_rounding_order: int) None

Prints results into the txt file and saves them.

Parameters
  • filename (str) -- filename string (should end with .txt)

  • print_rounding_order (int) -- print precision

Returns

None

dump_to_json(print_rounding_order: int) str

JSON serialization.

Parameters

print_rounding_order (int) -- print precision

Returns

A JSON-type object of results output.

Return type

str

export_to_json(filename: str, print_rounding_order: int) None

Dump the output dict into an JSON file.

Parameters
  • filename (str) -- filename string (should end with .json)

  • print_rounding_order (int) -- print precision

Returns

None

class chemsynthcalc.chem_output.ReactionOutput(chemical_reaction_output: dict)

Bases: object

Outputs for chemsynthcalc.chemical_reaction.ChemicalReaction

A collection of methods to output the results of chemsynthcalc.chemical_reaction.ChemicalReaction.The default filenames of the output files are "CSC_reaction" with target compound and nanoseconds since the epoch.

Parameters

chemical_formula_output (dict) -- output of chemsynthcalc.chemical_reaction.ChemicalReaction

print_results(print_rounding_order: int) None

Print results in the terminal.

Parameters

print_rounding_order (int) -- print precision

Returns

None

export_to_txt(filename: str, print_rounding_order: int) None

Prints results into the txt file and saves it.

Parameters
  • filename (str) -- filename string (should end with .txt)

  • print_rounding_order (int) -- print precision

Returns

None

dump_to_json(print_rounding_order: int) str

JSON serialization.

Parameters

print_rounding_order (int) -- print precision

Returns

A JSON-type object of results output.

Return type

str

export_to_json(filename: str, print_rounding_order: int) None

Dump output dict into JSON flie.

Parameters
  • filename (str) -- filename string (should end with .json)

  • print_rounding_order (int) -- print precision

Returns

None

chemsynthcalc.chemical_formula module

class chemsynthcalc.chemical_formula.ChemicalFormula(formula: str = '', rounding_order: int = 8)

Bases: object

A base class for representing a single chemical formula.

It constructs with a formula string and calculates properties: parsed formula, molar mass, mass percent, atomic percent, oxide percent from this string using chemsynthcalc.formula_parser.ChemicalFormulaParser and chemsynthcalc.molar_mass.MolarMassCalculation.

Parameters
  • formula (srt) -- string of chemical formula

  • rounding_order (int) -- value of rounding precision (8 by default)

Raises
  • ValueError -- if the input string is empty

  • ValueError -- if rounding order <= 0

Examples

>>> ChemicalFormula("H2O")
H2O
>>> ChemicalFormula("H2O").molar_mass
18.015
>>> ChemicalFormula("H2O").mass_percent
{'H': 11.19067444, 'O': 88.80932556}
property parsed_formula: dict

Formula parsed into dict.

Returns

Parsed dictionary representation of formula string created by chemsynthcalc.formula_parser.ChemicalFormulaParser.

Return type

dict

Example

>>> ChemicalFormula("K2SO4").parsed_formula
{'K': 2.0, 'S': 1.0, 'O': 4.0}
property molar_mass: float

Molar mass of formula.

Returns

The molar mass of the formula (in g/mol), calculated from parsed the formula using chemsynthcalc.molar_mass.MolarMassCalculation.

Return type

float

Example

>>> ChemicalFormula("K2SO4").molar_mass
174.252
property mass_percent: dict

The percentage of mass of atoms in the formula.

Returns

A mass percent or relative mass fraction of atoms in parsed chemical formula. The values of mass content are in % (with 100% sum), not fraction.

Return type

dict

Example

>>> ChemicalFormula("K2SO4").mass_percent
{'K': 44.87523816, 'S': 18.39864105, 'O': 36.72612079}
property atomic_percent: dict

Atomic percents of atoms in the formula.

Returns

An atomic percent or relative mole fraction dictionary of atoms in a parsed chemical formula. The values of mole content are in % (with 100% sum), not fraction.

Return type

dict

Example

>>> ChemicalFormula("K2SO4").atomic_percent
{'K': 28.57142857, 'S': 14.28571429, 'O': 57.14285714}
property oxide_percent: dict

Oxide percents of metals in formula.

Returns

An oxide percent or oxide fraction dictionary of atoms in parsed chemical formula. Oxide types are listed in the chemsynthcalc.periodic_table file and can be changed to any oxide formula. The values of oxide content are in % (with 100% sum), not fraction.

Return type

dict

Example

>>> ChemicalFormula("K2SO4").oxide_percent
{'K2O': 54.05676836, 'SO3': 45.94323164}
property output_results: dict

Dictionary of the calculation result output for class.

Returns

Output dictionary for all properties listed above.

Return type

dict

Example

>>> ChemicalFormula("H2O").output_results
{'formula': 'H2O',
'parsed formula': {'H': 2.0, 'O': 1.0},
'molar mass': 18.015,
'mass percent': {'H': 11.19067444, 'O': 88.80932556},
'atomic percent': {'H': 66.66666667, 'O': 33.33333333},
'oxide percent': {'H2O': 100.0}}
print_results(print_rounding_order: int = 4) None

Method to print a final result of calculations in terminal.

Parameters

print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

export_to_txt(filename: str = 'default', print_rounding_order: int = 4) None

Method to print the final result of the calculations in a txt file.

Parameters
  • filename (str) -- filename string (should end with .txt)

  • print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

as_json(print_rounding_order: int = 4) str

Serialization of output into JSON object.

Parameters

print_rounding_order (int) -- print precision (4 digits by default)

Returns

A JSON-type object of results output.

Return type

str

export_to_json(filename: str = 'default', print_rounding_order: int = 4) None

Method to print a final result of calculations in a JSON file.

Parameters
  • filename (str) -- filename string (should end with .json)

  • print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

chemsynthcalc.chemical_reaction module

class chemsynthcalc.chemical_reaction.ChemicalReaction(reaction: str = '', target: int = 0, mode: str = 'balance', target_mass: float = 1.0, rounding_order: int = 8, try_comb: bool = False)

Bases: object

A class that represents a chemical reaction and do operations on it.

There are three calculation modes:

1. The "force" mode is used when a user enters coefficients in the reaction string and wants the masses to be calculated whether the reaction is balanced or not.

2. "check" mode is the same as force, but with reaction balance checks.

3. "balance" mode tries to automatically calculate coefficients from the reaction string.

Important

Unlike other properties of this class, the chemsynthcalc.chemical_reaction.ChemicalReaction.coefficients property can be set directly.

Parameters
  • reaction (str) -- a reaction string

  • target (int) -- index of target compound (0 by default, or first compound in the products)

  • mode (str) -- coefficients calculation mode

  • target_mass (float) -- desired mass of target compound (in grams)

  • rounding_order (int) -- value of rounding precision (8 by default)

  • try_comb (bool) -- flag, which determines whether an attempt will be made to equalize the reaction using the combinatorial method in the "balance" mode

allowed_symbols

characters that allowed in the reaction string

Type

str

possible_reaction_separators

list of characters that can be used as reactants-products separator

Type

list

reactant_separator

character that can be used as compounds separator

Type

str

types_of_modes

allowed types of calculation modes

Type

list

algorithm

currently used calculation algorithm

Type

str

Raises
  • ValueError -- if rounding order <=0

  • NoSuchMode -- if mode is not in types_of_modes

  • ValueError -- if target is out of bounds of product list

  • ValueError -- if target < 0

  • ValueError -- if target_mass <=0

Examples

>>> ChemicalReaction("H2+O2=H2O")
H2+O2=H2O
>>> ChemicalReaction("2H2+O2=2H2O", mode="balance").coefficients
[2, 1, 2]
>>> ChemicalReaction("2H2+O2=2H2O", mode="check").masses
[0.11190674, 0.88809326, 1.0]
property reaction: str

Initial reaction

Returns

Initial reaction string with validity check.

Return type

str

Raises
  • ValueError -- if the reaction string is empty

  • InvalidCharacter -- if some of characters in the string are invalid

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").reaction
KMnO4+HCl=MnCl2+Cl2+H2O+KCl
property separator: str

Reactants-product separator.

Returns

Separator between reactants and products of chemical reaction.

Return type

str

Raises

NoSeparator -- if no separator was found in the reaction string

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").separator
=
property reactants: list

List of initially split reactants (left side of the reaction string).

Returns

Formulas on the left side are split by reactant_separator (+) and include initial coefficients (in case of force or check modes).

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").reactants
['KMnO4', 'HCl']
property products: list

List of initially split products (right side of the reaction string).

Returns

Formulas on the right side that have been split by reactant_separator (+) and include initial coefficients (in case of force or check modes).

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").products
['MnCl2', 'Cl2', 'H2O', 'KCl']
property compounds: list

List of all initially split products (left side and right side).

Returns

Sum of reactants and products

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").compounds
['KMnO4', 'HCl', 'MnCl2', 'Cl2', 'H2O', 'KCl']
property initial_coefficients: list

Initial coefficients

The coefficients are not equal to 1 in case if they have been entered (generally the case for force and check modes).

Returns

List of initial coefficients striped from the compounds.

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").initial_coefficients
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
property formulas: list

Decomposition of a list of formulas from the reaction string.

Returns

Every formula is striped from coefficient and become the chemsynthcalc.chemical_formula.ChemicalFormula object.

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").formulas
[KMnO4, HCl, MnCl2, Cl2, H2O, KCl]
property parsed_formulas: list

List of parsed formulas of chemsynthcalc.chemical_formula.ChemicalFormula objects list.

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").parsed_formulas
[{'K': 1.0, 'Mn': 1.0, 'O': 4.0}, {'H': 1.0, 'Cl': 1.0}, {'Mn': 1.0, 'Cl': 2.0}, {'Cl': 2.0}, {'H': 2.0, 'O': 1.0}, {'K': 1.0, 'Cl': 1.0}]
property matrix: numpy.array

Chemical reaction matrix.

The first implementation of reaction matrix method is probably belongs to Blakley. In general, a chemical reaction matrix is composed of the coefficients of each atom in each compound, giving a 2D array. The matrix composes naturally from previously parsed formulas.

Returns

2D array of each atom amount in each formula

Return type

np.array

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").matrix
[[1. 0. 0. 0. 0. 1.]  (K)
 [1. 0. 1. 0. 0. 0.]  (Mn)
 [4. 0. 0. 0. 1. 0.]  (O)
 [0. 1. 0. 0. 2. 0.]  (H)
 [0. 1. 2. 2. 0. 1.]] (Cl)
property reactant_matrix: numpy.array

Left half of the reaction matrix

Returns

2D array of each atom amount in each reactant

Return type

np.array

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").reactant_matrix
[[1. 0.]  (K)
 [1. 0.]  (Mn)
 [4. 0.]  (O)
 [0. 1.]  (H)
 [0. 1.]] (Cl)
property product_matrix: numpy.array

Right half of the reaction matrix

Returns

2D array of each atom amount in each product

Return type

np.array

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").product_matrix
[[0. 0. 0. 1.]  (K)
 [1. 0. 0. 0.]  (Mn)
 [0. 0. 1. 0.]  (O)
 [0. 0. 2. 0.]  (H)
 [2. 2. 0. 1.]] (Cl)
property molar_masses: list

List of molar masses (in g/mol)

Returns

List of molar masses of each compound in compounds

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").molar_masses
[158.032, 36.458, 125.838, 70.9, 18.015, 74.548]
property coefficients: list

Coefficients of the chemical reaction.

There are 3 possible modes that the method can run:

1) force mode is when coefficients are entered by user in reaction string and the calculation and the calculation takes place regardless of reaction balance (it gives warning if reaction is not balanced);

2) check mode is basically the force mode but it will raise an error if reaction is not balanced and will not calculate masses);

3) balance mode uses one of three auto-balancing aglorithms described in detail in the chemsynthcalc.reaction_balance.Balancer class.

In the fisrt two cases, the coefficients are just stripped from original formulas entered by user. In case of balance mode, coefficients are calculated.

Important

Unlike other properties of this class, this property can be set directly.

Raises

ReactionNotBalanced -- if reaction is not balanced in "check" mode.

Returns

list of reaction coefficients None: if it cannot balance the reaction

Return type

list

Examples

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl", mode="balance").coefficients
[2, 16, 2, 5, 8, 2]
>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl", mode="check")
>>> reaction.coefficients = [2, 16, 2, 5, 8, 2]
>>> reaction.coefficients
[2, 16, 2, 5, 8, 2]
>>> ChemicalReaction("2H2+2O2=H2O", mode="force").coefficients
[2, 2, 1]
property normalized_coefficients: list

List of coefficients normalized on target compound.

target coefficient = 1.0

Returns

Normalized coefficients.

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").normalized_coefficients
[1, 8, 1, 2.5, 4, 1]
property is_balanced: bool

Is the reaction balanced?

Returns

True if the reaction is balanced with current coefficients

Return type

bool

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").is_balanced
True
property final_reaction: str

Final representation of the reaction with coefficients.

Returns

string of the final reaction

Return type

str

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").final_reaction
"2KMnO4+16HCl=2MnCl2+5Cl2+8H2O+2KCl"
property final_reaction_normalized: str

Final representation of the reaction with normalized coefficients.

Returns

String of the final normalized reaction

Return type

str

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").final_reaction_normalized
"KMnO4+8HCl=MnCl2+2.5Cl2+4H2O+KCl"
property masses: list

List of masses of compounds (in grams).

List of masses of the of formulas in reaction calculated with coefficients obtained by any of the 3 methods. Calculates masses by calculating amount of substance nu (nu=mass/molar mass). Coefficients of reaction are normalized to the target. After nu of target compound is calculated, it broadcasted to other compound (with respect to their coefficients).

Returns

List of masses of compound

Return type

list

Examples

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").masses
[1.25583687, 2.31777365, 1.0, 1.40855703, 0.57264101, 0.59241247]
>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl", target_mass=2.0).masses
[2.51167374, 4.63554729, 2.0, 2.81711407, 1.14528203, 1.18482493]
property output_results: dict

Collection of every output of calculated chemical reaction properties.

Returns

All outputs collected in one dictionary.

Return type

dict

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").output_results
{'initial reaction': 'KMnO4+HCl=MnCl2+Cl2+H2O+KCl',
'reaction matrix': array([[1., 0., 0., 0., 0., 1.],
[1., 0., 1., 0., 0., 0.],
[4., 0., 0., 0., 1., 0.],
[0., 1., 0., 0., 2., 0.],
[0., 1., 2., 2., 0., 1.]]),
'mode': 'balance',
'formulas': [KMnO4, HCl, MnCl2, Cl2, H2O, KCl],
'coefficients': [2, 16, 2, 5, 8, 2],
'normalized coefficients': [1, 8, 1, 2.5, 4, 1],
'algorithm': 'inverse',
'is balanced': True,
'final reaction': '2KMnO4+16HCl=2MnCl2+5Cl2+8H2O+2KCl',
'final reaction normalized': 'KMnO4+8HCl=MnCl2+2.5Cl2+4H2O+KCl',
'molar masses': [158.032, 36.458, 125.838, 70.9, 18.015, 74.548],
'target': MnCl2,
'masses': [1.25583687, 2.31777365, 1.0, 1.40855703, 0.57264101, 0.59241247]}
coefficients_check(coefficients: list) bool

Checking the coefficients.

Parameters

coefficients (list) -- list of coefficients

Raises
Returns

True, if coefficients are good.

Return type

bool

Examples

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> reaction.coefficients = [2, 16, 2, 5, 8, 2]
>>> reaction.coefficients_check(reaction.coefficients)
True
>>> reaction.coefficients = [2, 16, 2, 5, 8]
>>> reaction.coefficients_check(reaction.coefficients)
chemsynthcalc.chem_errors.BadCoeffiecients: number of coefficients should be equal to 6
>>> reaction.coefficients = None
>>> reaction.coefficients_check(reaction.coefficients)
chemsynthcalc.chem_errors.BadCoeffiecients: Coefficients are None
>>> reaction.coefficients = [2, 16, 2, 5, 8, 0]
>>> reaction.coefficients_check(reaction.coefficients)
chemsynthcalc.chem_errors.BadCoeffiecients: 0 or -x in coefficients
check_elements_count() set

Checks if all elements are present in both sides of the reaction.

Does not work in the force mode!

Returns

Set of atom differences on the left and right sides of the reaction.

Return type

set

Examples

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").check_elements_count()
None
>>> ChemicalReaction("KMnHoO4+HCl=MnCl2+Cl2+H2O+KCl").check_elements_count()
chemsynthcalc.chem_errors.ReactantProductDifference: Cannot balance this
reaction, because element(s) {'Ho'} are only in one part of the reaction
to_integer(coefficients: list) list

Cast a float to integer in a list if it is integer.

Parameters

coefficients (list) -- list of coefficients

Returns

List of intified coefficients.

Return type

list

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").to_integer([1.0, 8.0, 1.0, 2.5, 4.0, 1.0])
[1, 8, 1, 2.5, 4, 1]
balance_reaction(algorithm: str = 'inv', intify: bool = True, max_comb: int = 100000000.0) list

High-level function call for all balancing algorithms.

Options availiable are: 1) "inv" - matrix inverse Thorne algorithm 2) "gpinv" - general pseudoinverse Risteski algorithm 3) "ppinv" - partial pseudoinverse Risteski algorithm 4) "comb" - combinatorial algorithm

Important

"comb" algorithm works only for integer coefficients less than 127 (see Balancer.comb_algorithm for details).

Parameters
  • algorithm (str) --

  • intify (bool) --

  • max_comb (int) --

Returns

List of obtained coefficients.

Return type

list

Examples

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").balance_reaction(algorithm="inv", intify=True)
[2, 16, 2, 5, 8, 2]
>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").balance_reaction(algorithm="gpinv", intify=False)
[0.19607843137254966, 1.568627450980392, 0.1960784313725499, 0.49019607843137436, 0.7843137254901958, 0.19607843137254813]
generate_final_reaction(coefs: list) str

Final reaction string with connotated formulas and calculated coefficients.

Parameters

coefs (list) -- list of coefficients

Returns

String of the final reaction

Return type

str

Example

>>> ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl").generate_final_reaction([2, 16, 2, 5, 8, 2])
"2KMnO4+16HCl=2MnCl2+5Cl2+8H2O+2KCl"
print_results(print_rounding_order: int = 4) None

Method to print a final result of calculations in terminal.

Parameters

print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

export_to_txt(filename: str = 'default', print_rounding_order: int = 4) None

Method to print a final result of calculations in txt file.

Parameters
  • filename (str) -- filename string (should end with .txt)

  • print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

as_json(print_rounding_order: int = 4) str

Serialization of output into JSON object.

Argruments:

print_rounding_order (int): print precision (4 digits by default).

Returns

JSON object of the output results.

Return type

str

export_to_json(filename: str = 'default', print_rounding_order: int = 4) None

Method to print a final result of calculations in JSON file.

Parameters
  • filename (str) -- filename string (should end with .json)

  • print_rounding_order (int) -- print precision (4 digits by default)

Returns

None

chemsynthcalc.chemutils module

chemsynthcalc.chemutils.arguments_type_checking(argument, *args) None

Checks for type of function argument.

Argments:

argument (Any): Argument of the function in question types (Any): Types that allowed for this argument

Raises

TypeError -- if agrument type is not one of specified types

Returns

None

chemsynthcalc.chemutils.find_lcm(int_list: list) int

Finds least common multiple of the list of integers.

Parameters

int_list (list) -- list of integers

Returns

Least common multiple

Return type

int

Example

>>> chemsynthcalc.chemutils.find_lcm([10,20,30]
60
chemsynthcalc.chemutils.find_gcd(int_list: list) int

Finds the greatest common divider of the list of integers.

Parameters

int_list (list) -- list of integers

Returns

greatest common divider

Return type

int

Example

>>> chemsynthcalc.chemutils.find_gcd([10,20,30]
10
chemsynthcalc.chemutils.stripe_formula_from_coefficients(formula) tuple

A function to stripe the initially parsed formulas from chemical reaction string.

Parameters

formula (str) -- a formula string

Returns

(float, str) tuple of (coefficient, reaction)

Return type

tuple

Example

>>> chemsynthcalc.chemutils.stripe_formula_from_coefficients("4.3H3PO4")
(4.3, 'H3PO4')

chemsynthcalc.formula_parser module

class chemsynthcalc.formula_parser.ChemicalFormulaParser(formula: str)

Bases: object

Parser of chemical formulas.

Methods of this class take string of compound chemical formula and turn it into a dict of atoms as keys and their coefficients as values.

Parameters

formula (str) -- formula string

atom_regex

regular expression for finding atoms in formula

Type

str

coefficient_regex

regular expression for atoms amounts in formula

Type

str

atom_and_coefficient_regex

atom_regex+coefficient_regex

Type

str

opener_brackets

opener brackets variations

Type

str

closer_brackets

closer brackets variations

Type

str

adduct_symbols

symbols for adduct notation (water of crystallization most often)

Type

str

allowed_symbols

regular expression for all symbols allowed in the formula string

Type

str

list_of_atoms

list of all atoms in the periodic table

Type

list

are_brackets_balanced() bool

Check if all kinds of brackets come in pairs.

Returns

True if all brackets are in pairs

Return type

bool

Examples

>>> ChemicalFormulaParser("(K2SO4)*H2O").are_brackets_balanced()
True
>>> ChemicalFormulaParser("(K2SO4)*H2O").are_brackets_balanced()
False
is_adduct_one() bool

Check if there is only one adduct in formula

Returns

True if there is only one adduct symbol

Return type

bool

Examples

>>> ChemicalFormulaParser("K2SO4*H2O").is_adduct_one()
True
>>> ChemicalFormulaParser("K2SO4*H2O*CO2").is_adduct_one()
False

Checks if all parsed atoms belong to the periodic table.

Parameters

parsed (dict) -- dictionary of parsed atoms

Raises

NoSuchAtom -- if one of the parsed atoms are not in the periodic table

Returns

None

Examples

>>> ChemicalFormulaParser("K2SO4*H2O").are_atoms_legal({'K': 2.0, 'S': 1.0, 'O': 5.0, 'H': 2.0})
None
>>> ChemicalFormulaParser("KHuSO4*H2O").are_atoms_legal({'K': 1.0, 'Hu':1.0, 'S': 1.0, 'O': 5.0, 'H': 2.0})
chemsynthcalc.chem_errors.NoSuchAtom: No atom Hu in the periodic table!
parse_formula() dict

Parse the formula and return a dict with occurrences of each atom.

Raises
Returns

Dictionary of parsed atoms

Return type

dict

Examples

>>> ChemicalFormulaParser("H2O").parse_formula()
{'H': 2.0, 'O': 1.0}
>>> ChemicalFormulaParser("C2H5OH").parse_formula()
{'C': 2.0, 'H': 6.0, 'O': 1.0}
>>> ChemicalFormulaParser("(K0.6Na0.4)2SO4*7H2O").parse_formula()
{'K': 1.2, 'Na': 0.8, 'S': 1.0, 'O': 11.0, 'H': 14.0}

chemsynthcalc.molar_mass module

class chemsynthcalc.molar_mass.MolarMassCalculation(parsed_formula: dict)

Bases: object

Class for the calculation of molar masses and percentages of compounds.

Compounds should be parsed by chemsynthcalc.formula_parser.ChemicalFormulaParser first.

Parameters

parsed_formula (dict) -- formula parsed by chemsynthcalc.formula_parser.ChemicalFormulaParser

atomicWeight

list of (atom, weight) tuple formed from chemsynthcalc.periodic_table

Type

list

list_of_atoms

list of atoms formed from chemsynthcalc.periodic_table

Type

list

calculate_molar_mass() float

Calculation of the molar mass of compound from the atomic masses of atoms in a parsed formula.

Atomic masses are taken from chemsynthcalc.periodic_table file.

Returns

molar mass (in g/mol)

Return type

float

Examples

>>> MolarMassCalculation({'H':2, 'O':1}).calculate_molar_mass()
18.015
>>> MolarMassCalculation({'C':2, 'H':6, 'O':1}).calculate_molar_mass()
46.069
calculate_mass_percent() dict

Calculation of mass percents of atoms in parsed formula.

Returns

mass percentages of atoms in formula

Return type

dict

Examples

>>> MolarMassCalculation({'H':2, 'O':1}).calculate_mass_percent()
{'H': 11.19067443796836, 'O': 88.80932556203163}
>>> MolarMassCalculation({'C':2, 'H':6, 'O':1}).calculate_mass_percent()
{'C': 52.14352384466777, 'H': 13.12813388612733, 'O': 34.72834226920489}
calculate_atomic_percent() dict

Calculation of atomic percents of atoms in the parsed formula.

Returns

atomic percentages of atoms in formula

Return type

dict

Examples

>>> MolarMassCalculation({'H':2, 'O':1}).calculate_atomic_percent()
{'H': 66.66666666666666, 'O': 33.33333333333333
>>> MolarMassCalculation({'C':2, 'H':6, 'O':1}).calculate_atomic_percent()
{'C': 22.22222222222222, 'H': 66.66666666666666, 'O': 11.11111111111111}
calculate_oxide_percent() dict

Calculation of oxide percents in parsed formula.

Calculation of oxide percents in parsed formula from the types of oxide declared in the periodic table file. This type of data is mostly used in XRF spectrometry and mineralogy. The oxide percents are calculated by finding the convertion factor between element and its respective oxide (https://www.geol.umd.edu/~piccoli/probe/molweight.html) and normalizing the total sum to 100%. One can change the oxide type for certain elements in the chemsynthcalc.periodic_table file. Theoretically, this function should work for other types of binary compound (sulfides, fluorides etc.) or even salts, however, modification of this function is required (for instance, in case of binary compound, removing X atom from the list of future compounds should have X as an argument of this function)

Returns

oxide percentages of oxides in formula

Return type

dict

Examples

>>> MolarMassCalculation({'C':2, 'H':6, 'O':1}).calculate_oxide_percent()
{'CO2': 61.9570190690046, 'H2O': 38.04298093099541}
>>> MolarMassCalculation({'Ba':1, 'Ti':1, 'O':3}).calculate_oxide_percent()
{'BaO': 65.7516917244869, 'TiO2': 34.24830827551309}

chemsynthcalc.periodic_table module

chemsynthcalc.periodic_table.periodic_table = [('H', 1.008, 2.2, 'H2O'), ('He', 4.0026, 1.2, 'He'), ('Li', 6.94, 0.98, 'Li2O'), ('Be', 9.0122, 1.57, 'BeO'), ('B', 10.81, 2.04, 'B2O3'), ('C', 12.011, 2.55, 'CO2'), ('N', 14.007, 3.04, 'NO2'), ('O', 15.999, 3.44, 'O'), ('F', 18.998, 3.98, 'F2O'), ('Ne', 20.18, 1.3, 'Ne'), ('Na', 22.99, 0.93, 'Na2O'), ('Mg', 24.305, 1.31, 'MgO'), ('Al', 26.982, 1.61, 'Al2O3'), ('Si', 28.085, 1.9, 'SiO2'), ('P', 30.974, 2.19, 'P2O3'), ('S', 32.06, 2.58, 'SO3'), ('Cl', 35.45, 3.16, 'ClO2'), ('Ar', 39.95, 2.2, 'Ar'), ('K', 39.098, 0.82, 'K2O'), ('Ca', 40.078, 1.0, 'CaO'), ('Sc', 44.956, 1.36, 'Sc2O3'), ('Ti', 47.867, 1.54, 'TiO2'), ('V', 50.942, 1.63, 'V2O5'), ('Cr', 51.996, 1.66, 'Cr2O3'), ('Mn', 54.938, 1.55, 'MnO2'), ('Fe', 55.845, 1.83, 'Fe2O3'), ('Co', 58.933, 1.88, 'Co2O3'), ('Ni', 58.693, 1.91, 'NiO'), ('Cu', 63.546, 1.9, 'Cu2O'), ('Zn', 65.38, 1.65, 'ZnO'), ('Ga', 69.723, 1.81, 'Ga2O3'), ('Ge', 72.63, 2.01, 'GeO2'), ('As', 74.922, 2.18, 'As2O3'), ('Se', 78.971, 2.55, 'Se3O4'), ('Br', 79.904, 2.96, 'BrO2'), ('Kr', 83.798, 3.0, 'Kr'), ('Rb', 85.468, 0.82, 'Rb2O'), ('Sr', 87.62, 0.95, 'SrO'), ('Y', 88.906, 1.22, 'Y2O3'), ('Zr', 91.224, 1.33, 'ZrO2'), ('Nb', 92.906, 1.6, 'Nb2O5'), ('Mo', 95.95, 2.16, 'MoO3'), ('Tc', 98.906, 1.9, 'TcO2'), ('Ru', 101.07, 2.2, 'RuO2'), ('Rh', 102.91, 2.28, 'Rh2O3'), ('Pd', 106.42, 2.2, 'PdO'), ('Ag', 107.87, 1.93, 'Ag2O'), ('Cd', 112.41, 1.69, 'CdO'), ('In', 114.82, 1.78, 'In2O3'), ('Sn', 118.71, 1.96, 'SnO2'), ('Sb', 121.76, 2.05, 'Sb2O3'), ('Te', 127.6, 2.1, 'TeO3'), ('I', 126.9, 2.66, 'I2O5'), ('Xe', 131.29, 2.6, 'Xe'), ('Cs', 132.91, 0.79, 'Cs2O'), ('Ba', 137.33, 0.89, 'BaO'), ('La', 138.91, 1.1, 'La2O3'), ('Ce', 140.12, 1.12, 'CeO2'), ('Pr', 140.91, 1.13, 'Pr2O3'), ('Nd', 144.24, 1.14, 'Nd2O3'), ('Pm', 146.92, 1.13, 'Pm2O3'), ('Sm', 150.36, 1.17, 'Sm2O3'), ('Eu', 151.96, 1.2, 'Eu2O3'), ('Gd', 157.25, 1.2, 'Gd2O3'), ('Tb', 158.93, 1.1, 'Tb2O3'), ('Dy', 162.5, 1.22, 'Dy2O3'), ('Ho', 164.93, 1.23, 'Ho2O3'), ('Er', 167.26, 1.24, 'Er2O3'), ('Tm', 168.93, 1.25, 'Tm2O3'), ('Yb', 173.05, 1.1, 'Yb2O3'), ('Lu', 174.97, 1.27, 'Lu2O3'), ('Hf', 178.49, 1.3, 'HfO2'), ('Ta', 180.95, 1.5, 'Ta2O5'), ('W', 183.84, 2.36, 'WO3'), ('Re', 186.21, 1.9, 'Re2O7'), ('Os', 190.23, 2.2, 'OsO3'), ('Ir', 192.22, 2.2, 'Ir2O3'), ('Pt', 195.08, 2.28, 'PtO'), ('Au', 196.97, 2.54, 'Au2O3'), ('Hg', 200.59, 2.0, 'HgO2'), ('Tl', 204.38, 1.62, 'Tl2O'), ('Pb', 207.2, 2.33, 'PbO2'), ('Bi', 208.98, 2.02, 'Bi2O3'), ('Po', 208.98, 2.0, 'PoO2'), ('At', 209.99, 2.2, 'At2O'), ('Rn', 222.02, 2.2, 'Rn'), ('Fr', 223.02, 0.79, 'Fr2O'), ('Ra', 226.03, 0.9, 'RaO'), ('Ac', 227.03, 1.1, 'Ac2O3'), ('Th', 232.04, 1.3, 'ThO2'), ('Pa', 231.04, 1.5, 'Pa2O5'), ('U', 238.03, 1.38, 'UO2'), ('Np', 237.05, 1.36, 'NpO2'), ('Pu', 244.06, 1.28, 'PuO2'), ('Am', 243.06, 1.13, 'AmO2'), ('Cm', 247.07, 1.28, 'Cm2O3'), ('Bk', 247.07, 1.3, 'BkO2'), ('Cf', 251.08, 1.3, 'Cf2O3'), ('Es', 252.08, 1.3, 'Es2O3'), ('Fm', 257.1, 1.3, 'Fm2O3'), ('Md', 258.1, 1.3, 'Md2O3'), ('No', 259.1, 1.3, 'No2O3'), ('Lr', 262, 1.3, 'Lr2O3'), ('Rf', 267, 1.3, 'RfO2'), ('Db', 268, 1.3, 'Db2O5'), ('Hs', 269, 1.3, 'SgO3'), ('Bh', 270, 1.3, 'Bh2O7'), ('Sg', 271, 1.3, 'HsO4'), ('Mt', 278, 1.3, 'Mt2O3'), ('Ds', 281, 1.3, 'DsO2'), ('Rg', 281, 1.3, 'RgO'), ('Nh', 284, 1.3, 'CnO2'), ('Cn', 285, 1.3, 'Nh2O3'), ('Fl', 289, 1.3, 'FlO2'), ('Mc', 289, 1.3, 'Mc2O5'), ('Lv', 292, 1.3, 'LvO3'), ('Ts', 294, 1.3, 'Ts2O7'), ('Og', 294, 1.3, 'Og')]

Periodic table of elements in the form of (element symbol, atomic weight, electronegativity, oxide formula). The abridged standard atomic weights are taken from https://doi.org/10.1515/pac-2019-0603. The weights of the radioactive elements are taken from https://iupac.qmul.ac.uk/AtWt/. Pauling electronegativities are taken from https://www.webelements.com/periodicity/eneg_pauling/. Pauling electronegativities for elements with unknown electronegativities (Bk-Og) are set to 1.3.

chemsynthcalc.reaction_balance module

class chemsynthcalc.reaction_balance.Balancer(reactant_matrix: numpy.array, product_matrix: numpy.array, rounding_order: int, intify: bool, try_comb: bool, max_comb: int = 100000000.0)

Bases: object

A class for balancing chemical equations automatically by different matrix methods

Currently implemented: Thorne algorithm (see inv_algorithm() method for details), Risteski general pseudo-inverse algorithm (see gpinv_algorithm() method for details), Risteski partial pseudo-inverse algorithm (see ppinv_algorithm() method for details), and naive combinational search algorithm (see comb_algorithm() for details). Class takes two matrices: matrix of reactants and matrix of products of chemical reaction, derived from general reaction matrix. Matrices are in the form of NumPy 2D array.

Note

Why use scipy.linalg.pinv, when numpy.linalg.pinv is doing the same thing and does not require the whole scipy import?

There are some peculiar reaction cases where (especially for ppinv_algorithm() method) the results for numpy.linalg.pinv differs from system to system (np version, OS, python version etc.). My understanding is that the cause of this behaviour lies in small differences for pinv algorithm in numpy C-libraries and BLAS-libraries, hence the difference. To avoid this, the more consistent scipy.linalg.pinv was method used.

Argumetns:

reactant_matrix (np.array): matrix of reactants property generated by chemsynthcalc.chemical_reaction.ChemicalReaction class

product_matrix (np.array): matrix of products property generated by chemsynthcalc.chemical_reaction.ChemicalReaction class

rounding_order (int): coefficients rounding precision

intify (bool): determines whether the coefficients should be integers

try_comb (bool): flag, which determines whether an attempt will be made to equalize the reaction using the combinatorial method

reaction_matrix

sum of reactant_matrix and product_matrix

Type

np.array

coef_limit

max integer coefficient for intify_coefficients()

Type

int

calculate_coefficients_inv() list

High-level function call to calculate coefficients using inverse Thorne algorithm.

Returns

list of calculated coefficients None: if cannot calculate

Return type

list

Example

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_inv()
[2, 16, 2, 5, 8, 2]
calculate_coefficients_gpinv() list

High-level function call to calculate coefficients using general Risteski algorithm.

Returns

list of calculated coefficients None: if cannot calculate

Return type

list

Example

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_gpinv()
[2, 16, 2, 5, 8, 2]
calculate_coefficients_ppinv() list

High-level function call to calculate coefficientsusing partial Risteski algorithm.

Returns

list of calculated coefficients None: if cannot calculate

Return type

list

Example

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_ppinv()
[2, 16, 2, 5, 8, 2]
calculate_coefficients_comb() list

High-level function call to calculate coefficients using a combinatorial algorithm.

Returns

list of calculated coefficients None: if cannot calculate

Return type

list

Example

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_comb()
[2, 16, 2, 5, 8, 2]
calculate_coefficients_auto() list

Automatically balance the chemical reaction.

A method that tries to automatically balance the chemical reaction. by sequentially applying the three calculation methods to the reaction matrix: a Thorne algorithm inv_algorithm(), two Risteski algorithms ppinv_algorithm() and gpinv_algorithm() and, if try_comb flag == True, a combinatorial algorithm comb_algorithm().

Returns

list of calculated coefficients and str of algorithm used None: if cannot calculate

Return type

tuple

Examples

>>> reaction = ChemicalReaction("KMnO4+HCl=MnCl2+Cl2+H2O+KCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_auto()
([2, 16, 2, 5, 8, 2], 'inverse')
>>> reaction = ChemicalReaction("H2O2+KNO3+H2SO4=K2SO4+NO+H2O+O2")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_auto()
([73, 118, 59, 59, 118, 132, 125], 'general pseudoinverse')
>>> reaction = ChemicalReaction("NH4ClO4+HNO3+HCl=HClO4+NOCl+N2O+N2O3+H2O+Cl2")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).calculate_coefficients_auto()
([64, 167, 137, 80, 43, 64, 30, 240, 39], 'general pseudoinverse')
static is_reaction_balanced(reactant_matrix: numpy.array, product_matrix: numpy.array, coefficients: list, tolerance: float = 1e-08) bool

Is reaction balanced with specified coefficients.

Checks if reaction is balanced by multiplying reactant matrix and product matrix by the respective coefficient vector. Method is static to call it outside of balancer instance.

Parameters
Returns

True if balanced within tolerance

Return type

bool

Examples

>>> reaction = ChemicalReaction("NH4ClO4+HNO3+HCl=HClO4+NOCl+N2O+N2O3+H2O+Cl2")
>>> Balancer.is_reaction_balanced(reaction.reactant_matrix, reaction.product_matrix, [64, 167, 137, 80, 43, 64, 30, 240, 39])
True
>>> reaction = ChemicalReaction("H2+O2=H2O")
>>> Balancer.is_reaction_balanced(reaction.reactant_matrix, reaction.product_matrix, [2,2,2])
False
round_up_coefficients(coefficients: list, order: int) list

Round up the float coefficient to int.

Round up the float coefficient if it contains a series of the same digit (i.e. 3.00000000009). This function is needed to fix inevitable floating point math errors.

Note

There is probably a better and faster way to do it.

Parameters
  • coefficients (list) -- List of coefficients to round

  • order (int) -- rounding precision

Returns

list of rounded coefficients

Return type

list

Example

>>> reaction = ChemicalReaction("P2O3+HClO3+H2O=H3PO4+HCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).round_up_coefficients([1.500000000000001, 1.0, 4.500000000000002, 3.0000000000000013, 1.0000000000000002], 8))
[1.5, 1.0, 4.5, 3.0, 1.0]
intify_coefficients(coefficients: list, limit: int) list

Reduce the coefficients to integers by finding the greatest common divider.

Parameters
  • coefficients (list) -- List of coefficients to intify

  • limit (int) -- upper limit (max int coef)

Returns

list of intified coefficients

Return type

list

Example

>>> reaction = ChemicalReaction("P2O3+HClO3+H2O=H3PO4+HCl")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).intify_coefficients([1.5, 1.0, 4.5, 3.0, 1.0], 100000)
[3, 2, 9, 6, 2]
inv_algorithm() list

Matrix inverse algorithm for reaction balancing.

A reaction matrix inverse algorithm proposed by Thorne. The calculation is based on the nullity, or dimensionality, of the matrix.

The algorithm can be described in steps:

  1. If the number of rows is greater than the number of columns, add zero columns until the matrix becomes square (Note: this is a modification of the original Thorne method described in the article).

  2. If reaction matrix is square (which means that the number of atoms involved is equal to the number of compounds) than we turn matrix in its row-echelon form by singular value decomposition.

  3. Calculation of the nullity of the matrix, which is basically number of compounds minus rank of the matrix.

  4. Create a matrix augumented by nullity number of rows of flipped identity matrix. If any rows are zeros, replace them with identity matrix rows.

  5. Inverse the augumented matrix.

  6. Exctract and transpose rightmost column.

  7. Normalize this value with the absolute min value of the vector.

  8. Round up float operations errors.

The absolute values of this vector are coefficients of the reaction.

Note

While this method works great for reactions with 0 and 1 nullity, it generally cannot work with nullities 2 and higher. Thorne claims that for higher nullities, a nullity number of vectors should be extracted, and each of them contains a set of correct coefficients. However, if number of rows in augmentation flipped identity matrix is 2 or more, one can easily see that each vector will contain nullity-1 zeroes, therefore they cannot be a correct vector of coefficients.

Returns

list of calculated coefficients

Return type

list

Examples

>>> reaction = ChemicalReaction("Bi2O3+TiO2=Bi4Ti3O12")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).inv_algorithm()
[2.0, 3.0, 1.0]
>>> reaction = ChemicalReaction("NH3+Br2=N2+NH4Br")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).inv_algorithm()
[8.0, 3.0, 1.0, 6.0]
>>> reaction = ChemicalReaction("Zn+H2S2O7=ZnSO4+H2S+H2O")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).inv_algorithm()
[4.0, 2.5, 4.0, 1.0, 1.5]
gpinv_algorithm() list

Matrix gerenal pseudoinverse algorithm for reaction balancing.

A reaction matrix pseudoinverse algorithm proposed by Risteski. There are other articles and methods of chemical equation balancing by this author, however, this particular algorithm seems to be most convenient for matrix calculations. The algorithm can be described in steps:

  1. Stack reactant matrix and negative product matrix.

  2. Calculate MP pseudoinverse of this matrix.

  3. Calculate coefficients by formula: x = (I – A+A)a, where x is the coefficients vector, I - identity matrix, A+ - MP inverse, A - matrix, a - arbitrary vector (in this case, vector of ones).

Note

This method is more general than Thorne's method, although it has some its own peculiarities. First of all, the output of this method is float, so, to generate an int coefs list, it needs to be converted, which is not always leads to a good result. Secondly, MP pseudoinverse is sensetive to row order in the reaction matrix. The rows should be ordered by atoms apperances in the reaction string.

Returns

list of calculated coefficients

Return type

list

Examples

>>> reaction = ChemicalReaction("Bi2O3+TiO2=Bi4Ti3O12")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).gpinv_algorithm()
[0.857142857142856, 1.285714285714286, 0.42857142857142894]
>>> reaction = ChemicalReaction("NH3+Br2=N2+NH4Br")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).gpinv_algorithm()
[1.3090909090909086, 0.49090909090909124, 0.16363636363636305, 0.9818181818181823]
>>> reaction = ChemicalReaction("Zn+H2S2O7=ZnSO4+H2S+H2O")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).gpinv_algorithm()
[1.2530120481927716, 0.7831325301204817, 1.253012048192771, 0.313253012048193, 0.4698795180722889]
ppinv_algorithm() list

Matrix partial pseudoinverse algorithm for reaction balancing.

A reaction matrix pseudoinverse algorithm also proposed by Risteski. The method is founded on virtue of the solution of a Diophantine matrix equation by using of a Moore-Penrose pseudoinverse matrix.

The algorithm can be described in steps:

  1. Take the Moore-Penrose pseudoinverse of the reactant matrix.

  2. Create a G matrix in the form of (I-AA^-)B, where I is the identity matrix, A is the reactant matrix, A^- is the MP pseudoinverse of A and B is the product matrix.

  3. Then, the vector y (coefficients of products) is equal to (I-G^-G)u.

  4. Vector x (coefficients of reactants) is equal to A^-By + (I-A^-A)v, where u and v are columns of ones.

Note

While this algorithm and gpinv_algorithm() are very similar, there are some differences in output results. This method exists mostly for legacy purposes, like balancing following reactions according to Risteski.

Returns

list of calculated coefficients

Return type

list

Examples

>>> reaction = ChemicalReaction("PtNH3BrNO3+CuNH3KNO3+BeCO3=C44H50O14.98+Cu(NO3)2+PtO3+Br1.99NO2+K1.97O+BeO+HNO3")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).ppinv_algorithm()
[0.13568057806893347, 0.5130378112503738, 1.533818182010022, 0.03485950413659115, 0.5130378112503766, 0.13568057806893571, 0.06818119500951737, 0.26042528489867056, 1.5338181820100212, 0.20317996112835507]
>>> reaction = ChemicalReaction("PtNH3BrNO3+(Fe(CN)3)4(Fe(CN)2)3+C44H50O15+Cu(NO3)2+K2BeO2=CuNH3KNO3+BeCO3+K3.97Fe(CN)6+PtO2+Br1.96NO2+HNO3")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).ppinv_algorithm()
[1.0653080872224086, 0.02084998005190298, 0.03200884162226492, 1.236558074626148, 0.9079895101341948, 1.2365580746261489, 0.9079895101341948, 0.145949860363285, 1.0653080872224083, 0.5435245342971473, 1.0866921189021224]
>>> reaction = ChemicalReaction("KAu(CN)2+AgRuAuTe8+Fe2(SO4)3+N2Se4+WO3+Na2CO3+H2CO3+HCl=[Ru(C10H8N2)3]Cl2*6H2O+C4H3AuNa1.96OS7+[WCl4(NSeCl)]2+K3.98Fe(CN)6+Au2O3+TeO3+AgO+NO2")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).ppinv_algorithm()
[3.077274686056925, 0.071072198453605, 0.3865922972433353, 0.03396659573785036, 0.13586638295139766, 0.1623687648421996, 1.117085035989227, 0.8214763116641697, 0.07107219845360468, 0.16568241310428458, 0.06793319147569614, 0.7731845944866663, 1.491332235703123, 0.5685775876288415, 0.07107219845360557, 1.021075422996532]
comb_algorithm(max_number_of_iterations: int = 100000000.0) list

Matrix combinatorial algorithm for reaction balancing.

Finds a solution solution of a Diophantine matrix equation by simply enumerating of all possible solutions of number_of_iterations coefficients. The solution space is created by Cartesian product (in this case, np.meshgrid function), and therefore it is very limited by memory. There must a better, clever and fast solution to this!

Important

Only for integer coefficients less than 128. Only for reactions with total compound count <=10. A CuPy GPU-accelerated version of this method is available in the source code.

Note

All possible variations of coefficients vectors are combinations = max_coefficients**number_of_compounds, therefore this method is most effective for reaction with small numbers of compounds.

Returns

list of calculated coefficients

Return type

list

Examples

>>> reaction = ChemicalReaction("KMnO4+H2S+H2SO4=S+MnSO4+K2SO4+H2O")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).comb_algorithm()
[2, 2, 2, 1, 2, 1, 4]
>>> reaction = ChemicalReaction("H2O2+KNO3+H2SO4=K2SO4+NO+H2O+O2")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).comb_algorithm()
[1, 2, 1, 1, 2, 2, 2]
>>> reaction = ChemicalReaction("Fe2O3+C=Fe3O4+FeO+Fe+Fe3C+CO+CO2")
>>> Balancer(reaction.reactant_matrix, reaction.product_matrix, 8, True, True).comb_algorithm()
[4, 5, 1, 1, 1, 1, 1, 3]

chemsynthcalc.reaction_matrix module

class chemsynthcalc.reaction_matrix.ChemicalReactionMatrix(parsed_all: list)

Bases: object

Class that creates a reaction matrix from parsed formulas of the parsed reaction string.

Parameters

parsed_all (list) -- list of all parsed formulas

merged_dict

merged total dict of all parsed formulas

Type

dict

electronegativity

list of (atom, electronegativity) tuples formed from chemsynthcalc.periodic_table file

Type

list

electronegativity_pattern

list of atoms sorted by their Pauling electronegativities

Type

list

list_of_atoms

list of atoms from chemsynthcalc.periodic_table file.

Type

list

create_reaction_matrix() numpy.array

Create chemical reaction matrix.

Method that creates a chemical matrix of reaction from the list of parsed compound. Initially contains a species type (atom label) at the start of each row of matrix (might be used in case of future expansion of matrix representation in print). Retruns 2D NumPy array (since Matrix class is no longer recommended https://numpy.org/doc/stable/reference/generated/numpy.matrix.html).

Returns

the 2D array of chemical reaction matrix (amounts of all atoms in all compounds of reaction)

Return type

np.array

Example

>>> parsed = ChemicalReaction("H2+O2=H2O").parsed_formulas
>>> ChemicalReactionMatrix(parsed).create_reaction_matrix()
[[2. 0. 2.]
 [0. 2. 1.]]