Commit d45673a3 authored by eladnoor's avatar eladnoor

renaming the Compound and Reaction classes

parent 059060fd
Pipeline #50596636 (#144) failed with stage
in 16 minutes and 39 seconds
......@@ -30,8 +30,7 @@ del get_versions
import numpy as np
from equilibrator_cache import Compound
from equilibrator_cache import CompoundCache
from equilibrator_cache import CompoundCache, BaseCompound, BaseReaction
from equilibrator_cache.thermodynamic_constants import (
FARADAY, POSSIBLE_REACTION_ARROWS, Q_, R, default_I, default_pH,
default_pMg, default_T, physiological_concentration,
......@@ -52,6 +51,7 @@ def strip_units(v: np.array) -> np.array:
from equilibrator_api.bounds import Bounds
from equilibrator_api.pathway import Pathway
from equilibrator_api.phased_reaction import PhasedReaction as Reaction
from equilibrator_api.phased_compound import Compound
from equilibrator_api.phased_reaction import Reaction
from equilibrator_api.component_contribution import ComponentContribution
from equilibrator_api.thermo_models import PathwayThermoModel
......@@ -33,7 +33,7 @@ import pkg_resources
from numpy import log
from . import (
Q_, Compound, ccache, default_conc_lb, default_conc_ub,
Q_, BaseCompound, ccache, default_conc_lb, default_conc_ub,
standard_concentration, ureg)
......@@ -44,7 +44,7 @@ class BaseBounds(object):
"""Return a (deep) copy of self."""
raise NotImplementedError
def GetLowerBound(self, compound: Compound):
def GetLowerBound(self, compound: BaseCompound):
"""Get the lower bound for this key.
Args:
......@@ -52,7 +52,7 @@ class BaseBounds(object):
"""
raise NotImplementedError
def GetUpperBound(self, compound: Compound):
def GetUpperBound(self, compound: BaseCompound):
"""Get the upper bound for this key.
Args:
......@@ -62,7 +62,7 @@ class BaseBounds(object):
def GetLowerBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Iterable[float]:
"""Get the bounds for a set of keys in order.
......@@ -73,7 +73,7 @@ class BaseBounds(object):
def GetUpperBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Iterable[float]:
"""Get the bounds for a set of keys in order.
......@@ -82,17 +82,17 @@ class BaseBounds(object):
"""
return map(self.GetUpperBound, compounds)
def GetBoundTuple(self, compound: Compound) -> Tuple[float, float]:
def GetBoundTuple(self, compound: BaseCompound) -> Tuple[float, float]:
"""Get both upper and lower bounds for this key.
:param compound: a Compound object
:param compound: a BaseCompound object
:return: a 2-tuple (lower bound, upper bound)
"""
return self.GetLowerBound(compound), self.GetUpperBound(compound)
def GetBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Tuple[Iterable[float], Iterable[float]]:
"""Get the bounds for a set of compounds.
......@@ -115,7 +115,7 @@ class BaseBounds(object):
def GetLnBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Tuple[Iterable[float], Iterable[float]]:
"""Get the log-bounds for a set of compounds.
......@@ -128,7 +128,7 @@ class BaseBounds(object):
def GetLnLowerBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Iterable[float]:
"""Get the log lower bounds for a set of compounds.
......@@ -140,7 +140,7 @@ class BaseBounds(object):
def GetLnUpperBounds(
self,
compounds: Iterable[Compound]
compounds: Iterable[BaseCompound]
) -> Iterable[float]:
"""Get the log upper bounds for a set of compounds.
......@@ -151,7 +151,7 @@ class BaseBounds(object):
return map(self.conc2ln_conc, ubs)
@ureg.check(None, None, '[concentration]', '[concentration]')
def SetBounds(self, compound: Compound, lb: float, ub: float):
def SetBounds(self, compound: BaseCompound, lb: float, ub: float):
"""Set bounds for a specific key.
Args:
......@@ -173,8 +173,8 @@ class Bounds(BaseBounds):
@ureg.check(None, None, None, '[concentration]', '[concentration]')
def __init__(self,
lower_bounds: Dict[Compound, float] = None,
upper_bounds: Dict[Compound, float] = None,
lower_bounds: Dict[BaseCompound, float] = None,
upper_bounds: Dict[BaseCompound, float] = None,
default_lb: float = default_conc_lb,
default_ub: float = default_conc_ub) -> object:
"""Initialize the bounds object.
......@@ -212,8 +212,8 @@ class Bounds(BaseBounds):
provided
:return: a Bounds object
"""
lbs: Dict[Compound, float] = dict()
ubs: Dict[Compound, float] = dict()
lbs: Dict[BaseCompound, float] = dict()
ubs: Dict[BaseCompound, float] = dict()
bounds_df = pd.read_csv(f)
for row in bounds_df.itertuples():
......@@ -244,7 +244,7 @@ class Bounds(BaseBounds):
bounds_unit: str = None,
default_lb: float = default_conc_lb,
default_ub: float = default_conc_ub
) -> Tuple[object, Dict[Compound, str]]:
) -> Tuple[object, Dict[BaseCompound, str]]:
"""Read bounds from a Pandas DataFrame.
:param df: a pandas.DataFrame with the bounds
......@@ -318,7 +318,7 @@ class Bounds(BaseBounds):
self.default_lb,
self.default_ub)
def GetLowerBound(self, compound: Compound) -> float:
def GetLowerBound(self, compound: BaseCompound) -> float:
"""Get the lower bound for this key.
:param compound: a compound
......@@ -326,7 +326,7 @@ class Bounds(BaseBounds):
"""
return self.lower_bounds.get(compound, self.default_lb)
def GetUpperBound(self, compound: Compound):
def GetUpperBound(self, compound: BaseCompound):
"""Get the upper bound for this key.
:param compound: a compound
......
......@@ -32,7 +32,7 @@ import numpy as np
from component_contribution import GibbsEnergyPredictor
from . import FARADAY, R, default_I, default_pH, default_pMg, default_T, ureg
from .phased_reaction import PhasedReaction
from .phased_reaction import Reaction
class ComponentContribution(object):
......@@ -69,7 +69,7 @@ class ComponentContribution(object):
return R * self.temperature
@staticmethod
def standard_dg(reaction: PhasedReaction) -> Tuple[float, float]:
def standard_dg(reaction: Reaction) -> Tuple[float, float]:
"""Calculate the chemical reaction energies of a reaction.
:param reaction: the input Reaction object
......@@ -87,7 +87,7 @@ class ComponentContribution(object):
@staticmethod
def standard_dg_multi(
reactions: List[PhasedReaction]) -> Tuple[np.array, np.array]:
reactions: List[Reaction]) -> Tuple[np.array, np.array]:
"""Calculate the chemical reaction energies of a list of reactions.
Using the major microspecies of each of the reactants.
......@@ -106,7 +106,7 @@ class ComponentContribution(object):
def standard_dg_prime(
self,
reaction: PhasedReaction
reaction: Reaction
) -> Tuple[float, float]:
"""Calculate the transformed reaction energies of a reaction.
......@@ -134,7 +134,7 @@ class ComponentContribution(object):
def dg_prime(
self,
reaction: PhasedReaction
reaction: Reaction
) -> Tuple[float, float]:
"""Calculate the dG'0 of a single reaction.
......@@ -150,7 +150,7 @@ class ComponentContribution(object):
def standard_dg_prime_multi(
self,
reactions: List[PhasedReaction]
reactions: List[Reaction]
) -> Tuple[np.array, np.array]:
"""Calculate the transformed reaction energies of a list of reactions.
......@@ -179,14 +179,14 @@ class ComponentContribution(object):
def physiological_dg_prime(
self,
reaction: PhasedReaction
reaction: Reaction
) -> Tuple[float, float]:
"""Calculate the dG'm of a single reaction.
Assume all aqueous reactants are at 1 mM, gas reactants at 1 mbar and
the rest at their standard concentration.
:param reaction: an object of type PhasedReaction
:param reaction: an object of type Reaction
:return: a tuple (dG_r_prime, dG_uncertainty) where dG_r_prime is
the estimated Gibbs free energy of reaction and dG_uncertainty is the
standard deviation of estimation. Multiply it by 1.96 to get a 95%
......@@ -198,7 +198,7 @@ class ComponentContribution(object):
self.RT * reaction.physiological_dg_correction()
return physiological_dg_prime, dg_uncertainty
def ln_reversibility_index(self, reaction: PhasedReaction) -> float:
def ln_reversibility_index(self, reaction: Reaction) -> float:
"""Calculate the reversibility index (ln Gamma) of a single reaction.
:return: ln_RI - The reversibility index (in natural log scale).
......@@ -211,10 +211,10 @@ class ComponentContribution(object):
ln_RI = (2.0 / abs_sum_coeff) * physiological_dg_prime / self.RT
return ln_RI
def standard_e_prime(self, reaction: PhasedReaction) -> Tuple[float, float]:
def standard_e_prime(self, reaction: Reaction) -> Tuple[float, float]:
"""Calculate the E'0 of a single half-reaction.
:param reaction: a PhasedReaction object
:param reaction: a Reaction object
:return: a tuple (E0_prime, E0_uncertainty) where E0_prime is
the estimated standard electrostatic potential of reaction and
E0_uncertainty is the standard deviation of estimation. Multiply it
......@@ -237,11 +237,11 @@ class ComponentContribution(object):
def physiological_e_prime(
self,
reaction: PhasedReaction
reaction: Reaction
) -> Tuple[float, float]:
"""Calculate the E'0 of a single half-reaction.
:param reaction: a PhasedReaction object
:param reaction: a Reaction object
:return: a tuple (E0_prime, E0_uncertainty) where E0_prime is
the estimated standard electrostatic potential of reaction and
E0_uncertainty is the standard deviation of estimation. Multiply it
......@@ -264,11 +264,11 @@ class ComponentContribution(object):
def e_prime(
self,
reaction: PhasedReaction
reaction: Reaction
) -> Tuple[float, float]:
"""Calculate the E'0 of a single half-reaction.
:param reaction: a PhasedReaction object
:param reaction: a Reaction object
:return: a tuple (E0_prime, E0_uncertainty) where E0_prime is
the estimated standard electrostatic potential of reaction and
E0_uncertainty is the standard deviation of estimation. Multiply it
......@@ -291,19 +291,19 @@ class ComponentContribution(object):
def dg_analysis(
self,
reaction: PhasedReaction
reaction: Reaction
) -> List[Dict[str, object]]:
"""Get the analysis of the component contribution estimation process.
:param reaction: a PhasedReaction object.
:param reaction: a Reaction object.
:return: the analysis results as a list of dictionaries
"""
return ComponentContribution.predictor.get_dg_analysis(reaction)
def is_using_group_contribution(self, reaction: PhasedReaction) -> bool:
def is_using_group_contribution(self, reaction: Reaction) -> bool:
"""Check whether group contribution is needed to get this reactions' dG.
:param reaction: a PhasedReaction object.
:param reaction: a Reaction object.
:return: true iff group contribution is needed
"""
return ComponentContribution.predictor.is_using_group_contribution(
......
......@@ -33,16 +33,15 @@ from io import IOBase
from typing import Callable, Iterable, List, TextIO, Tuple
import numpy as np
from equilibrator_cache.reaction import (
create_stoichiometric_matrix_from_reactions)
from sbtab import SBtab
from scipy.linalg import fractional_matrix_power
from . import (
Q_, Compound, R, default_I, default_pH, default_pMg, default_T, strip_units)
Q_, BaseCompound, BaseReaction, R, default_I, default_pH, default_pMg,
default_T, strip_units)
from .bounds import Bounds
from .component_contribution import ComponentContribution
from .phased_reaction import PhasedReaction
from .phased_reaction import Reaction
from .thermo_models import PathwayMDFData, PathwayThermoModel
......@@ -53,7 +52,7 @@ class Pathway(object):
"""
def __init__(self,
reactions: List[PhasedReaction],
reactions: List[Reaction],
fluxes: np.array,
standard_dg_primes: np.array = None,
dg_sigma: np.array = None,
......@@ -66,7 +65,7 @@ class Pathway(object):
"""Initialize.
Args:
reactions: a list of gibbs.reaction.Reaction objects.
reactions: a list of Reaction objects.
fluxes: numpy.array of relative fluxes in same order as reactions.
standard_dg_primes: reaction energies (in kJ/mol)
dg_sigma: square root of the uncertainty covariance matrix
......@@ -82,7 +81,8 @@ class Pathway(object):
else:
self._bounds = bounds.Copy()
self.S = create_stoichiometric_matrix_from_reactions(reactions)
self.S = BaseReaction.create_stoichiometric_matrix_from_reactions(
reactions)
self.fluxes = fluxes
assert self.fluxes.shape == (Nr, )
......@@ -167,7 +167,7 @@ class Pathway(object):
def set_compound_names(
self,
mapping: Callable[[Compound], str]
mapping: Callable[[BaseCompound], str]
) -> None:
"""Use alternative compound names for outputs such as plots.
......@@ -206,7 +206,7 @@ class Pathway(object):
self._bounds.GetLnUpperBounds(self.S.index))))
@staticmethod
def get_compounds(reactions: Iterable[PhasedReaction]) -> List[Compound]:
def get_compounds(reactions: Iterable[Reaction]) -> List[BaseCompound]:
"""Get a unique list of all compounds in all reactions.
:param reactions: an iterator of reactions
......@@ -243,7 +243,7 @@ class Pathway(object):
return map(str, self.reactions)
@property
def net_reaction(self) -> PhasedReaction:
def net_reaction(self) -> Reaction:
"""Calculate the sum of all the reactions in the pathway.
:return: the net reaction
......@@ -252,7 +252,7 @@ class Pathway(object):
net_rxn_stoich = self.S @ v
net_rxn_stoich = net_rxn_stoich[net_rxn_stoich != 0]
sparse = net_rxn_stoich.to_dict()
return PhasedReaction(sparse)
return Reaction(sparse)
@classmethod
def from_csv_file(cls,
......@@ -283,7 +283,7 @@ class Pathway(object):
flux = float(row.get('Flux', 0.0))
logging.debug('formula = %f x (%s)', flux, rxn_formula)
rxn = PhasedReaction.parse_formula(rxn_formula)
rxn = Reaction.parse_formula(rxn_formula)
rxn.check_full_reaction_balancing()
reactions.append(rxn)
......@@ -353,9 +353,9 @@ class Pathway(object):
reactions = []
reaction_ids = []
for row in reaction_df.itertuples():
rxn = PhasedReaction.parse_formula(row.ReactionFormula,
row.ID,
name_to_compound.get)
rxn = Reaction.parse_formula(row.ReactionFormula,
row.ID,
name_to_compound.get)
if not rxn.is_balanced(ignore_atoms=("H")):
warnings.warn(f"Reaction {rxn.rid} is not balanced")
reactions.append(rxn)
......
"""inherit from equilibrator_cache.models.compound.Compound an add phases."""
"""inherit from equilibrator_cache.BaseCompound an add phases."""
# The MIT License (MIT)
#
# Copyright (c) 2013 Weizmann Institute of Science
......@@ -30,11 +30,9 @@ from collections import namedtuple
from typing import Set, Tuple
import numpy as np
from equilibrator_cache import Compound
from equilibrator_cache.reaction import Reaction
from equilibrator_cache.thermodynamic_constants import legendre_transform
from . import Q_, R, ccache, ureg
from . import Q_, BaseCompound, R, ccache, ureg
AQUEOUS_PHASE_NAME = 'aqueous'
......@@ -189,53 +187,40 @@ class Condition(object):
if self.physiolical_abundance is None:
return True # when the phase does not allow relative abundances
else:
return self._abundance == self.standard_abundance
class PhasedCompound(object):
"""A class that combines a equilibrator_api Compound and a Condition."""
def __init__(self, compound: Compound, condition: Condition = None):
"""Create a new PhasedCompound object."""
self.compound = compound
self.condition = condition or Condition(self.possible_phases[0])
@staticmethod
def get_default(compound: Compound) -> Condition:
"""Get the default phase of a compound.
:param compound: a Compound
:return: the default phase
"""
if compound.mnx_id in NON_AQUEOUS_COMPOUND_DICT:
return Condition(NON_AQUEOUS_COMPOUND_DICT[compound.mnx_id][0])
else:
return Condition(AQUEOUS_PHASE_NAME)
return self._abundance == self.physiolical_abundance
@property
def mnx_id(self) -> str:
"""Get the compound's MetaNetX ID."""
return self.compound.mnx_id
def is_standard(self) -> bool:
"""Return True if the abundance is standard for this phase."""
return (
self.standard_abundance is None or
self._abundance == self.standard_abundance
)
@property
def id(self) -> int:
"""Get the compound's equilibrator internal ID."""
return self.compound.id
class Compound(BaseCompound):
"""A class that combines a equilibrator_api BaseCompound and a Condition."""
def __init__(self, compound: BaseCompound, condition: Condition = None):
"""Create a new Compound object."""
super(Compound, self).__init__()
self.id = compound.id
self.mnx_id = compound.mnx_id
self.inchi_key = compound.inchi_key
self.inchi = compound.inchi
self.smiles = compound.smiles
self.mass = compound.mass
self.atom_bag = compound.atom_bag
self.dissociation_constants = compound.dissociation_constants
self.group_vector = compound.group_vector
self.microspecies = compound.microspecies
self.identifiers = compound.identifiers
@property
def formula(self) -> str:
"""Get the chemical formula."""
return self.compound.formula
self.condition = condition or Condition(self.possible_phases[0])
@property
def html_formula(self) -> str:
"""Get the chemical formula."""
return re.sub(r'(\d+)', r'<sub>\1</sub>', self.compound.formula)
@property
def mass(self) -> float:
"""Get the chemical molecular mass."""
return self.compound.mass
return re.sub(r'(\d+)', r'<sub>\1</sub>', self.formula)
@property
def phase(self) -> str:
......@@ -245,7 +230,7 @@ class PhasedCompound(object):
@property
def phase_shorthand(self) -> str:
"""Get the phase shorthand (i.e. 'l' for liquid)."""
if self.compound.mnx_id == "MNXM60":
if self == ccache.co2_total:
# for CO2(total) there should be no indication of the phase,
# since it is actually a combination of gas and aqueous.
return ""
......@@ -260,7 +245,7 @@ class PhasedCompound(object):
:return:
"""
assert phase in self.possible_phases, (
f"The phase of {self.compound} must be one of the following: "
f"The phase of {self} must be one of the following: "
f"{str(self.possible_phases)}."
)
self.condition = Condition(phase)
......@@ -284,7 +269,7 @@ class PhasedCompound(object):
:param abundance: the new abundance in the correct units
:return:
"""
assert self.compound != Reaction.PROTON_COMPOUND, (
assert self != ccache.proton, (
f"Cannot directly change the relative abundance of H+. Use the pH "
f"parameter instead for adjusting this value."
)
......@@ -294,7 +279,7 @@ class PhasedCompound(object):
@property
def ln_abundance(self) -> float:
"""Return the log of the abundance (for thermodynamic calculations)."""
if self.compound == Reaction.PROTON_COMPOUND:
if self == ccache.proton:
# Since pH is an environmental parameter, we do not use the
# concentration of protons for energy calculations
return 0.0
......@@ -303,7 +288,7 @@ class PhasedCompound(object):
@property
def ln_physiological_abundance(self) -> float:
"""Return the log of the default physiological abundance."""
if self.compound == Reaction.PROTON_COMPOUND:
if self == ccache.proton:
# Since pH is an environmental parameter, we do not use the
# concentration of protons for energy calculations
return 0.0
......@@ -314,6 +299,11 @@ class PhasedCompound(object):
"""Check if the abundance is physiological."""
return self.condition.is_physiological
@property
def is_standard(self) -> bool:
"""Check if the abundance is standard."""
return self.condition.is_standard
@ureg.check(None, None, "[concentration]", "[temperature]")
def get_stored_standard_dgf_prime(
self,
......@@ -381,7 +371,7 @@ class PhasedCompound(object):
if ms is not None:
ms_list.append(ms.__dict__())
else:
for ms in self.compound.microspecies:
for ms in self.microspecies:
d = {"num_protons": ms.number_protons,
"charge": ms.charge,
"ddg_over_rt": ms.ddg_over_rt,
......@@ -398,9 +388,21 @@ class PhasedCompound(object):
def first_name(self):
"""Get the first name that appears in the compound-cache."""
# TODO: use MetaNetX database to get the first name
return ccache.get_compound_first_name(self.compound)
return ccache.get_compound_first_name(self)
@property
def names(self) -> Set[str]:
"""Get the set of all associated names in the compound cache."""
return ccache.get_compound_names(self.compound)
return ccache.get_compound_names(self)
def __str__(self) -> str:
s = super(Compound, self).__str__()
if self.condition.is_standard:
return f"{s}{self.phase_shorthand}"
else:
return f"{s}{self.phase_shorthand} [{self.abundance:.2g}]"
def __repr__(self):
return (
f"{type(self).__name__}(mnx_id={self.mnx_id}, phase={self.phase}, abundance={self.abundance})"
)
"""inherit from equilibrator_cache.reaction.Reaction an add phases."""
"""inherit from BaseReaction an add phases."""
# The MIT License (MIT)
#
# Copyright (c) 2013 Weizmann Institute of Science
......@@ -27,17 +27,16 @@
import logging
from typing import Dict, List, Tuple
from typing import Callable, Dict, List, Tuple
import numpy as np
from equilibrator_cache.reaction import Reaction
from . import Q_, Compound, ccache, ureg
from .phased_compound import PhasedCompound
from . import Q_, BaseCompound, BaseReaction, ccache, ureg
from .phased_compound import Compound
class PhasedReaction(Reaction):
"""A daughter class of Reaction that adds phases and abundances."""
class Reaction(BaseReaction):
"""A daughter class of BaseReaction that adds phases and abundances."""
REACTION_COUNTER = 0
......@@ -45,130 +44,148 @@ class PhasedReaction(Reaction):
self,
sparse: Dict[Compound, float],
arrow: str = "<=>",
rid: str = None,
sparse_with_phases: Dict[PhasedCompound, float] = None
rid: str = None
):
"""Create a PhasedReaction object.
"""Create a Reaction object.
:param sparse: a dictionary of Compounds to stoichiometric coefficients
:param sparse: a dictionary of PhasedCompounds to stoichiometric
coefficients
:param arrow: a string representing the arrow in the chemical formula
:param rid: a string of the reaction ID
"""
super(PhasedReaction, self).__init__(sparse, arrow, rid)
if sparse_with_phases is not None:
self.sparse_with_phases = sparse_with_phases
else:
self.sparse_with_phases = \
{PhasedCompound(cpd): coeff for cpd, coeff in sparse.items()}
super(Reaction, self).__init__(sparse, arrow, rid)
# convert any keys that are of type Compound to Compound
for compound in sparse.keys():
if type(compound) == Compound:
continue
elif type(compound) == BaseCompound:
coeff = self.sparse.pop(compound)
self.sparse[Compound(compound)] = coeff
else:
raise TypeError("All keys in 'sparse' must be of type "
"BaseCompound or Compound")
if self.rid is None:
self.rid = 'COCO:R%05d' % PhasedReaction.REACTION_COUNTER
PhasedReaction.REACTION_COUNTER += 1
self.rid = 'COCO:R%05d' % Reaction.REACTION_COUNTER
Reaction.REACTION_COUNTER += 1
@classmethod
def parse_formula(
cls,
formula: str,
rid: str = None,
str_to_compound: Callable[[str], BaseCompound] = ccache.get_compound,
) -> object:
"""
Parses a two-sided formula such as: 2 C00001 = C00002 + C00003
Args:
formula - a string representation of the chemical formula
name_to_cid - (optional) a dictionary mapping names to KEGG IDs
Return:
The set of substrates, products and the reaction direction
"""
rxn = BaseReaction.parse_formula(formula, rid, str_to_compound)
return Reaction(rxn.sparse, rxn.arrow, rxn.rid)
def clone(self):
"""Clone this reaction object."""
return PhasedReaction(self.sparse.copy(), self.arrow, self.rid,
self.sparse_with_phases.copy())
return Reaction(self.sparse.copy(), self.arrow, self.rid)
def reverse(self):
"""Return a PhasedReaction with the reverse reaction."""
"""Return a Reaction with the reverse reaction."""
sparse = {
cpd: -coeff for (cpd, coeff) in self.sparse.items()
cpd: -coeff for (cpd, coeff) in self.items()
}
sparse_with_phases = {
cpd: -coeff for (cpd, coeff) in self.sparse_with_phases.items()
cpd: -coeff for (cpd, coeff) in self.items()
}
return PhasedReaction(sparse, self.arrow, self.rid,
sparse_with_phases)
def set_abundance(self, compound: Compound, abundance: ureg.Quantity):
"""Set the abundance of the compound."""
for phased_compound in self.sparse_with_phases.keys():
if phased_compound.compound == compound:
phased_compound.abundance = abundance
return Reaction(sparse, self.arrow, self.rid)
def reset_abundances(self):
"""Reset the abundance to standard levels."""
for phased_compound in self.sparse_with_phases.keys():
for phased_compound in self.keys():
phased_compound.reset_abundance()
def set_phase(self, compound: Compound, phase: str):
"""Set the phase of the compound."""
for phased_compound in self.sparse_with_phases.keys():
if phased_compound.compound == compound:
phased_compound.phase = phase
def get_phased_compound(self, compound: BaseCompound) -> Compound:
"""Get the Compound object by the BaseCompound object."""
for phased_compound in self.keys():
if phased_compound == compound:
return phased_compound
return None