11. Global Configuration

This notebook example demonstrates how the global configuration object, the MassConfiguration, is used to configure the default behaviors for various COBRApy and MASSpy methods.

[1]:
import cobra

import mass
from mass.example_data import create_example_model

cobra_config = cobra.Configuration()

Note that changing the global configuration values is the most useful at the beginning of a work session.

11.1. The MassConfiguration Object

Similar to the cobra.Configuration object, the MassConfiguration object is a singleton, meaning that only one instance can exist and is respected everywhere in MASSpy.

The MassConfiguration is retrieved via the following:

[2]:
mass_config = mass.MassConfiguration()

The MassConfiguration is synchronized with the cobra.Configuration singleton object such that a change in one configuration object affects the other.

[3]:
print("cobra configuration before: {0!r}".format(cobra_config.bounds))
# Change bounds using the MassConfiguration object
mass_config.bounds = (-444, 444)
print("cobra configuration after: {0!r}".format(cobra_config.bounds))
cobra configuration before: (-1000.0, 1000.0)
cobra configuration after: (-444, 444)

This means that changes only need to be made to the MassConfiguration object for workflows that involve both the COBRApy and MASSpy packages. The shared configuration attributes can be viewed using the MassConfiguration.shared_state attribute.

[4]:
list(mass_config.shared_state)
[4]:
['solver',
 'tolerance',
 'lower_bound',
 'upper_bound',
 'processes',
 'cache_directory',
 'max_cache_size',
 'cache_expiration']

11.2. Attributes for Model Construction

The following attributes of the MassConfiguration alter default behaviors for constructing models and importing/exporting models via SBML.

[5]:
from mass import MassMetabolite, MassReaction

11.2.1. For irreversible reactions

When an irreversible reaction is created, the equilibrium constant and reverse rate constant are automatically set based on the irreversible_Keq and irreversible_kr attributes, respectively.

[6]:
mass_config.irreversible_Keq = float("inf")
mass_config.irreversible_kr = 0

print("Irreversible Keq: {0}".format(mass_config.irreversible_Keq))
print("Irreversible kr: {0}".format(mass_config.irreversible_kr))
R1 = MassReaction("R1", reversible=False)
R1.parameters
Irreversible Keq: inf
Irreversible kr: 0
[6]:
{'Keq_R1': inf, 'kr_R1': 0}

Changing the irreversible_Keq and irreversible_kr attributes affects newly created MassReaction objects.

[7]:
mass_config.irreversible_Keq = 10e6
mass_config.irreversible_kr = 1e-6
print("Irreversible Keq: {0}".format(mass_config.irreversible_Keq))
print("Irreversible kr: {0}\n".format(mass_config.irreversible_kr))

# Create new reaction
R2 = MassReaction("R2", reversible=False)
print(R2.parameters)
Irreversible Keq: 10000000.0
Irreversible kr: 1e-06

{'Keq_R2': 10000000.0, 'kr_R2': 1e-06}

Existing reactions are not affected.

[8]:
print(R1.parameters)
{'Keq_R1': inf, 'kr_R1': 0}

11.2.2. For rate expressions

Automatic generation of rate expressions are affected using the exclude_metabolites_from_rates and exclude_compartment_volumes_in_rates attributes.

[9]:
model = create_example_model("textbook")
Set parameter Username

11.2.2.1. Excluding metabolites from rates

The exclude_metabolites_from_rates attribute determines which metabolites to exclude from rate expressions by using a dictionary that contains a metabolite attribute for filtering, and a list of values to be excluded.

[10]:
mass_config.exclude_metabolites_from_rates
[10]:
{'elements': [{'H': 2, 'O': 1}, {'H': 1}]}

The default setting utilizes the MassMetabolite.elements attribute for filtering, excluding any metabolite that returns the elements for hydrogen and water.

[11]:
ENO = model.reactions.get_by_id("ENO")
print(ENO.rate)
kf_ENO*(_2pg_c(t) - pep_c(t)/Keq_ENO)

The exclude_metabolites_from_rates attribute can be changed by providing a dict that contains a metabolite attribute for filtering and the list of values to be excluded. For example, to exclude “2pg_c” by using its name attribute as the criteria for exclusion:

[12]:
mass_config.exclude_metabolites_from_rates = {"name": ["D-Glycerate 2-phosphate"]}
ENO = model.reactions.get_by_id("ENO")
print(ENO.rate)
kf_ENO*(1 - h2o_c(t)*pep_c(t)/Keq_ENO)

Or, to exclude hydrogen and water by using their identifiers:

[13]:
mass_config.exclude_metabolites_from_rates = {"id": ["h_c", "h2o_c"]}
ENO = model.reactions.get_by_id("ENO")
print(ENO.rate)
kf_ENO*(_2pg_c(t) - pep_c(t)/Keq_ENO)

Boundary reactions are unaffected by the exclude_metabolites_from_rates attribute:

[14]:
for rid in ["SK_h_c", "SK_h2o_c"]:
    reaction = model.reactions.get_by_id(rid)
    print(reaction.rate)
kf_SK_h_c*(h_c(t) - h_b/Keq_SK_h_c)
kf_SK_h2o_c*(h2o_c(t) - h2o_b/Keq_SK_h2o_c)

11.2.2.2. Excluding compartments from rates

The exclude_compartment_volumes_in_rates attribute determines whether compartment volumes are factored into rate expressions. By default, compartment volumes are not included in automatically generated rate expressions:

[15]:
PGI = model.reactions.get_by_id("PGI")
print(PGI.rate)
kf_PGI*(g6p_c(t) - f6p_c(t)/Keq_PGI)

When the exclude_compartment_volumes_in_rates attribute is set as False, compartments are included in rate expressions as volume_CID, with CID referring to the compartment identifier.

[16]:
mass_config.exclude_compartment_volumes_in_rates = False

PGI = model.reactions.get_by_id("PGI")
model.custom_parameters["volume_c"] = 1

print(PGI.rate)
kf_PGI*volume_c*(g6p_c(t) - f6p_c(t)/Keq_PGI)

The compartment volume is currently treated as a custom parameter. This behavior is subject to change in future updates following the release of COBRApy compartment objects.

11.2.3. For compartments and SBML

The boundary_compartment attribute defines the compartment for any external boundary species.

[17]:
# Create a boundary reaction
x1_c = MassMetabolite("x1_c", compartment="c")
R3 = MassReaction("R1")
R3.add_metabolites({x1_c: -1})

print(mass_config.boundary_compartment)
R3.boundary_metabolite
{'b': 'boundary'}
[17]:
'x1_b'

The boundary_compartment can be changed using a dict that contains the new compartment identifier and its full name.

[18]:
mass_config.boundary_compartment = {"xt": "external"}
R3.boundary_metabolite
[18]:
'x1_xt'

Because the mass.Simulation object uses the libRoadRunner package, a simulator for SBML models, a model cannot be simulated without defining at least one compartment. The default_compartment attribute is used to define the compartment of the model when no compartments have been defined.

[19]:
mass_config.default_compartment
[19]:
{'compartment': 'default_compartment'}

As with the boundary_compartment attribute, the default_compartment attribute can be changed using a dict:

[20]:
mass_config.default_compartment = {"def": "default_compartment"}
mass_config.default_compartment
[20]:
{'def': 'default_compartment'}

11.2.3.1. Model creator

SBML also allows for a model creator to be defined when exporting models:

[21]:
mass_config.model_creator
[21]:
{'familyName': '', 'givenName': '', 'organization': '', 'email': ''}

The model_creator attribute of the MassConfiguration allows the model creator to be set at the time of export by using a dict, with valid keys as “familyName”, “givenName”, “organization”, and “email”.

[22]:
mass_config.model_creator = {
    "familyName": "Smith",
    "givenName": "John",
    "organization": "Systems Biology Research Group @UCSD"}
mass_config.model_creator
[22]:
{'familyName': 'Smith',
 'givenName': 'John',
 'organization': 'Systems Biology Research Group @UCSD',
 'email': ''}

11.3. Attributes for Simulation and Analysis

The following attributes of the MassConfiguration alter default behaviors of various simulation and analytical methods.

[23]:
from mass import Simulation

# Reset configurations before loading model
mass_config.boundary_compartment = {"b": "boundary"}
mass_config.exclude_compartment_volumes_in_rates = True

model = create_example_model("Glycolysis")
sim = Simulation(model, verbose=True)
Successfully loaded MassModel 'Glycolysis' into RoadRunner.

11.3.1. Steady state threshold

The MassConfiguration.steady_state_threshold attribute determines whether a model has reached a steady state using the following criteria:

  • With simulations (i.e., strategy=simulate), the absolute difference between the last two solution points must be less than or equal to the steady state threshold.

  • With steady state solvers, the sum of squares of the steady state solutions must be less than or equal to the steady state threshold.

In general, compared values must be less than or equal to the steady_state_threshold attribute to be considered at a steady state.

[24]:
mass_config.steady_state_threshold = 1e-20
conc_sol, flux_sol = sim.find_steady_state(model, strategy="simulate")
bool(conc_sol)  # Empty solution objects return False
[24]:
True

Changing the threshold affects whether solution values are considered to be at steady state:

[25]:
mass_config.steady_state_threshold = 1e-6
conc_sol, flux_sol = sim.find_steady_state(model, strategy="simulate")
bool(conc_sol)  # Filled solution objects return False
[25]:
True

11.3.2. Decimal precision

The MassConfiguration.decimal_precision attribute is a special attribute used in several mass methods. The value of the attribute determines how many digits in rounding after the decimal to preserve.

For many methods, the decimal_precision attribute will not be applied unless a decimal_precision kwarg is set as True.

[26]:
# Set decimal precision
mass_config.decimal_precision = 8

# Will not apply decimal precision to steady state solutions
conc_sol, flux_sol = sim.find_steady_state(model, strategy="simulate",
                                           decimal_precision=False)
print(conc_sol["glc__D_c"])

# Will apply decimal precision to steady state solutions
conc_sol, flux_sol = sim.find_steady_state(model, strategy="simulate",
                                           decimal_precision=True)
print(conc_sol["glc__D_c"])
1.0000003633303345
1.00000036

If MassConfiguration.decimal_precision is None, no rounding will occur.

[27]:
mass_config.decimal_precision = None

# Will apply decimal precision to steady state solutions
conc_sol, flux_sol = sim.find_steady_state(model, strategy="simulate",
                                           decimal_precision=True)
print(conc_sol["glc__D_c"])
1.0000003633303345

11.4. Shared COBRA Attributes

The following attributes are those shared with the cobra.Configuration object.

11.4.1. Bounds

When a reaction is created, its default bound values are determined by the lower_bound and upper_bound attributes of the MassConfiguration:

[28]:
mass_config.lower_bound = -1000
mass_config.upper_bound = 1000
R4 = MassReaction("R4")
print("R4 bounds: {0}".format(R4.bounds))
R4 bounds: (-1000, 1000)

Changing the bounds affects newly created reactions, but not existing ones:

[29]:
mass_config.bounds = (-444, 444)
R5 = MassReaction("R5")
print("R5 bounds: {0}".format(R5.bounds))
print("R4 bounds: {0}".format(R4.bounds))
R5 bounds: (-444, 444)
R4 bounds: (-1000, 1000)

11.4.2. Solver

The default solver and solver tolerance attributes are determined by the solver and tolerance attributes of the MassConfiguration. The solver and tolerance attributes are utilized by newly instantiated models and ConcSolver objects.

[30]:
model = create_example_model("textbook")
print("Solver {0!r}".format(model.solver))
print("Tolerance {0}".format(model.tolerance))
Solver <optlang.gurobi_interface.Model object at 0x7fc160f23c70>
Tolerance 1e-07

The default solver can be changed, depending on the solvers installed in the current environment. GLPK is assumed to always be present in the environment.

The solver tolerance is similarly set using the tolerance attribute.

[31]:
# Change solver and solver tolerance
mass_config.solver = "glpk"
mass_config.tolerance = 1e-4

# Instantiate a new model to observe changes
model = create_example_model("textbook")
print("Solver {0!r}".format(model.solver))
print("Tolerance {0}".format(model.tolerance))
Solver <optlang.glpk_interface.Model object at 0x7fc149881c40>
Tolerance 0.0001

11.4.3. Number of processes

The MassConfiguration.processes determines the default number of processes used when multiprocessing is possible. The default number corresponds to the number of available cores (hyperthreads).

[32]:
mass_config.processes
[32]:
15