Reaction API¶
Reaction ¶
Chemical reaction with stoichiometric coefficients and thermodynamic evaluation.
The Reaction class supports: - Explicit coefficients for all species - Automatic coefficient calculation using atom conservation - Mixed explicit/auto coefficients for partially constrained systems
Coefficient Types¶
- Numeric (int, float): Explicit coefficient value
AutoorNone: Coefficient to be auto-calculated during balance()
Parameters¶
reactants : list[ReactionSpecies] List of reactant species with coefficients products : list[ReactionSpecies] List of product species with coefficients
Examples¶
All explicit coefficients¶
rxn = Reaction.from_smiles( ... reactants=[("CH4", 1), ("O2", 2)], ... products=[("CO2", 1), ("H2O", 2)] ... )
Full auto-balance¶
rxn = Reaction.from_smiles( ... reactants=["CH4", "O2"], # No coefficients -> all Auto ... products=["CO2", "H2O"] ... ) rxn.balance()
Mixed explicit/auto¶
rxn = Reaction.from_smiles( ... reactants=[("OCC(O)CO", 1), ("[H][]", Auto)], ... products=[("CC(O)CO", 1), ("O", Auto)] ... ) rxn.balance()
all_species
property
¶
All species in order: reactants then products.
coefficients
property
¶
Dictionary mapping formula to coefficient.
Returns coefficients in order: reactants (positive), products (positive). Note: For thermodynamic calculations, reactant coefficients are negated.
stoichiometry_vector
property
¶
Stoichiometry vector nu where nu_i < 0 for reactants, > 0 for products.
Returns None if any coefficient is undetermined.
enthalpy
property
¶
Standard enthalpy of reaction (Delta H_r) in kJ/mol.
Auto-balances if needed.
entropy
property
¶
Standard entropy of reaction (Delta S_r) in J/(mol*K).
Auto-balances if needed.
gibbs_free_energy
property
¶
Standard Gibbs free energy of reaction (Delta G_r) in kJ/mol at 298.15 K.
Calculated as: Delta G = Delta H - T * Delta S
from_smiles
classmethod
¶
from_smiles(reactants: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None, products: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None, *, reactant_smiles: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None, product_smiles: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None) -> Reaction
Create a Reaction from SMILES strings with optional coefficients.
Supports multiple input formats for flexibility:
-
Simple SMILES lists (all coefficients Auto):
Reaction.from_smiles(["CH4", "O2"], ["CO2", "H2O"])
-
Tuples with explicit coefficients:
Reaction.from_smiles( ... reactants=[("CH4", 1), ("O2", 2)], ... products=[("CO2", 1), ("H2O", 2)] ... )
-
Mixed explicit/Auto coefficients:
Reaction.from_smiles( ... reactants=[("OCC(O)CO", 1), ("[H][]", Auto)], ... products=[("CC(O)CO", 1), ("O", Auto)] ... )
-
Legacy keyword argument style:
Reaction.from_smiles( ... reactant_smiles=[("CH4", 1), ("O2", 2)], ... product_smiles=[("CO2", 1), ("H2O", 2)] ... )
Parameters¶
reactants : Sequence[str] | Sequence[tuple[str, CoeffSpec]] Reactant SMILES, optionally with coefficients products : Sequence[str] | Sequence[tuple[str, CoeffSpec]] Product SMILES, optionally with coefficients reactant_smiles : Sequence (keyword, legacy) Alternative way to specify reactants product_smiles : Sequence (keyword, legacy) Alternative way to specify products
Returns¶
Reaction New Reaction instance
Raises¶
ValueError If neither positional nor keyword arguments provided InvalidSmilesError If any SMILES string is invalid
from_reaction_smiles
classmethod
¶
Create a Reaction from a reaction SMILES string.
Format: 'coeff SMILES + coeff SMILES >> coeff SMILES + coeff SMILES' Coefficients are optional; if omitted, marked as Auto.
Parameters¶
reaction_smiles : str Reaction SMILES with '>>' separator auto_balance : bool If True, automatically balance after parsing (default: True)
Returns¶
Reaction Parsed reaction
Examples¶
rxn = Reaction.from_reaction_smiles("CH4 + 2 O2 >> CO2 + 2 H2O") rxn = Reaction.from_reaction_smiles("OCC(O)CO + [H][] >> CC(O)CO + O")
balance ¶
Balance the reaction by solving for unknown coefficients.
Uses the null-space algorithm for atom conservation: - For fully unconstrained: finds basis of null(A) and selects simplest solution - For partially constrained: solves the linear system with known coefficients
Parameters¶
normalize : bool If True, normalize so smallest coefficient is 1 (default: True) prefer_integers : bool If True, scale to get integer coefficients when possible (default: True)
Returns¶
Reaction Self (for method chaining)
Raises¶
OverconstrainedError If the constraints are inconsistent (no solution exists) UnderconstrainedError If multiple solutions exist (need more constraints)
Notes¶
The balancing problem is formulated as:
For m elements and n species with composition matrix A (m x n): A @ nu = 0 (atom conservation)
where nu is the stoichiometry vector (negative for reactants).
If some coefficients are known, we partition: A @ [nu_known; nu_unknown] = 0 which gives: A_unknown @ nu_unknown = -A_known @ nu_known
Examples¶
rxn = Reaction.from_smiles(["CH4", "O2"], ["CO2", "H2O"]) rxn.balance() print(rxn) CH4 + 2 O2 -> CO2 + 2 H2O
rxn = Reaction.from_smiles( ... reactants=[("OCC(O)CO", 1), ("[H][]", Auto)], ... products=[("CC(O)CO", 1), ("O", Auto)] ... ) rxn.balance() print(rxn.coefficients)
Class Overview¶
from phoenix import Reaction, Auto
rxn = Reaction.from_smiles(
reactants=[("CH4", 1), ("O=O", Auto)],
products=[("O=C=O", Auto), ("O", Auto)]
)
rxn.balance()
Auto Sentinel¶
Auto is a singleton sentinel value for auto-calculated coefficients.
# These are equivalent
rxn1 = Reaction.from_smiles(
reactants=[("CH4", Auto), ("O2", Auto)],
products=[("CO2", Auto), ("H2O", Auto)]
)
rxn2 = Reaction.from_smiles(
reactants=["CH4", "O2"],
products=["CO2", "H2O"]
)
Factory Methods¶
from_smiles¶
@classmethod
def from_smiles(
cls,
reactants: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None,
products: Sequence[str] | Sequence[tuple[str, CoeffSpec]] | None = None,
*,
reactant_smiles: Sequence[...] | None = None,
product_smiles: Sequence[...] | None = None,
) -> Reaction
Create a Reaction from SMILES strings.
Parameters:
| Name | Type | Description |
|---|---|---|
reactants |
Sequence | Reactant SMILES or (SMILES, coeff) tuples |
products |
Sequence | Product SMILES or (SMILES, coeff) tuples |
reactant_smiles |
Sequence | Legacy keyword argument |
product_smiles |
Sequence | Legacy keyword argument |
Coefficient Spec:
intorfloat: Explicit coefficientAutoorNone: Auto-calculate
Examples:
# All auto
rxn = Reaction.from_smiles(["CH4", "O2"], ["CO2", "H2O"])
# Mixed
rxn = Reaction.from_smiles(
reactants=[("CH4", 1), ("O2", Auto)],
products=[("CO2", Auto), ("H2O", Auto)]
)
from_reaction_smiles¶
@classmethod
def from_reaction_smiles(cls, reaction_smiles: str, auto_balance: bool = True) -> Reaction
Create from reaction SMILES format.
Format: "coeff SMILES + coeff SMILES >> coeff SMILES + coeff SMILES"
Examples:
rxn = Reaction.from_reaction_smiles("CH4 + 2 O2 >> CO2 + 2 H2O")
rxn = Reaction.from_reaction_smiles("CH4 + O2 >> CO2 + H2O", auto_balance=True)
Properties¶
Species Access¶
| Property | Type | Description |
|---|---|---|
reactants |
list[ReactionSpecies] | Reactant species |
products |
list[ReactionSpecies] | Product species |
all_species |
list[ReactionSpecies] | All species |
elements |
set[str] | Elements in reaction |
is_balanced |
bool | Whether balanced |
coefficients |
dict[str, float | None] |
stoichiometry_vector |
np.ndarray | None |
Thermodynamic Properties¶
| Property | Type | Description |
|---|---|---|
enthalpy / delta_h |
float | ΔH_rxn in kJ/mol |
entropy / delta_s |
float | ΔS_rxn in J/(mol·K) |
gibbs_free_energy / delta_g |
float | ΔG_rxn in kJ/mol |
Methods¶
balance¶
Balance the reaction.
Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
normalize |
bool | True | Normalize smallest coefficient to 1 |
prefer_integers |
bool | True | Convert to integers if possible |
Returns: Self (for chaining)
Raises:
OverconstrainedError- Inconsistent constraintsUnderconstrainedError- Multiple solutions
to_equation¶
Format as equation string.
Returns: "CH4 + 2 O2 -> CO2 + 2 H2O"
ReactionSpecies¶
ReactionSpecies
dataclass
¶
A species (compound) in a reaction with its stoichiometric coefficient.
Attributes¶
compound : Compound The chemical compound coefficient : float | None Stoichiometric coefficient (None if not yet determined) is_auto : bool Whether coefficient was marked for auto-calculation
Attributes¶
| Attribute | Type | Description |
|---|---|---|
compound |
Compound | The compound |
coefficient |
float | None |
is_auto |
bool | Was coefficient auto-calculated |
Properties¶
| Property | Type | Description |
|---|---|---|
formula |
str | Molecular formula |
composition |
dict[str, int] | Element counts |
Methods¶
Create copy with new coefficient.
Balancing Algorithm¶
Atom Conservation¶
For each element j:
Null-Space Method¶
When all coefficients unknown, find null(A) where A is the composition matrix.
Constrained System¶
When some coefficients known:
Examples¶
Full Auto-Balance¶
rxn = Reaction.from_smiles(["CH4", "O2"], ["CO2", "H2O"])
rxn.balance()
print(rxn) # CH4 + 2 O2 -> CO2 + 2 H2O
Partial Constraints¶
rxn = Reaction.from_smiles(
reactants=[("OCC(O)CO", 1), ("[H][H]", Auto)],
products=[("CC(O)CO", 1), ("O", Auto)]
)
rxn.balance()
print(rxn.coefficients)