U ("Up-regulator") up-regulates X , by sharing an upstream reagent S ("Source") across 2 separate reactions:¶2 S <-> U and S <-> X (both mostly forward)¶1st-order kinetics throughout.
Invoking Le Chatelier's principle, it can be seen that, starting from equilibrium, when [U] goes up, so does [S]; and when [S] goes up, so does [X].
Conversely, when [U] goes down, so does [S]; and when [S] goes down, so does [X].
This experiment is a counterpart of experiment up_regulate_2, with "upstream" rather than "downstream" reactions.
Note: numerical errors in the same reactions (with the same initial conditions) is explored in the experiment "large_time_steps_2"
LAST REVISED: Feb. 19, 2023
# Extend the sys.path variable, to contain the project's root directory
import set_path
set_path.add_ancestor_dir_to_syspath(2) # The number of levels to go up
# to reach the project's home, from the folder containing this notebook
Added 'D:\Docs\- MY CODE\BioSimulations\life123-Win7' to sys.path
from experiments.get_notebook_info import get_notebook_basename
from src.modules.reactions.reaction_data import ReactionData as chem
from src.modules.reactions.reaction_dynamics import ReactionDynamics
import numpy as np
import plotly.express as px
from src.modules.visualization.graphic_log import GraphicLog
# Initialize the HTML logging
log_file = get_notebook_basename() + ".log.htm" # Use the notebook base filename for the log file
# Set up the use of some specified graphic (Vue) components
GraphicLog.config(filename=log_file,
components=["vue_cytoscape_1"],
extra_js="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.21.2/cytoscape.umd.js")
-> Output will be LOGGED into the file 'up_regulate_3.log.htm'
# Initialize the system
chem_data = chem(names=["U", "X", "S"])
# Reaction 2 S <-> U , with 1st-order kinetics for all species (mostly forward)
chem_data.add_reaction(reactants=[(2, "S")], products="U",
forward_rate=8., reverse_rate=2.)
# Reaction S <-> X , with 1st-order kinetics for all species (mostly forward)
chem_data.add_reaction(reactants="S", products="X",
forward_rate=6., reverse_rate=3.)
chem_data.describe_reactions()
# Send the plot of the reaction network to the HTML log file
graph_data = chem_data.prepare_graph_network()
GraphicLog.export_plot(graph_data, "vue_cytoscape_1")
Number of reactions: 2 (at temp. 25 C) 0: 2 S <-> U (kF = 8 / kR = 2 / Delta_G = -3,436.56 / K = 4) | 1st order in all reactants & products 1: S <-> X (kF = 6 / kR = 3 / Delta_G = -1,718.28 / K = 2) | 1st order in all reactants & products [GRAPHIC ELEMENT SENT TO LOG FILE `up_regulate_3.log.htm`]
dynamics = ReactionDynamics(reaction_data=chem_data)
dynamics.set_conc(conc={"U": 50., "X": 100., "S": 0.})
dynamics.describe_state()
SYSTEM STATE at Time t = 0: 3 species: Species 0 (U). Conc: 50.0 Species 1 (X). Conc: 100.0 Species 2 (S). Conc: 0.0
dynamics = ReactionDynamics(reaction_data=chem_data)
dynamics.set_conc(conc={"U": 50., "X": 100., "S": 0.})
#dynamics.describe_state()
dynamics.set_diagnostics() # To save diagnostic information about the call to single_compartment_react()
dynamics.single_compartment_react(time_step=0.01, stop_time=1.5,
dynamic_substeps=4, rel_fast_threshold=50)
df = dynamics.get_history()
#df
dynamics.explain_time_advance()
single_compartment_react(): setting abs_fast_threshold to 50.0 150 total step(s) taken From time 0 to 0.44, in 176 substeps of 0.0025 (each 1/4 of full step) From time 0.44 to 1.5, in 106 FULL steps of 0.01 (for a grand total of the equivalent of 150 FULL steps)
dynamics.plot_curves(colors=['green', 'orange', 'blue'])
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium(tolerance=3)
2 S <-> U
Final concentrations: [U] = 72.24 ; [S] = 18.23
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.9635
Formula used: [U] / [S]
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 0.9125 %
Reaction IS in equilibrium (within 3% tolerance)
S <-> X
Final concentrations: [X] = 37.3 ; [S] = 18.23
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 2.04648
Formula used: [X] / [S]
2. Ratio of forward/reverse reaction rates: 2.0
Discrepancy between the two values: 2.324 %
Reaction IS in equilibrium (within 3% tolerance)
True
dynamics.describe_state()
SYSTEM STATE at Time t = 1.5: 3 species: Species 0 (U). Conc: 72.23775751588529 Species 1 (X). Conc: 37.298728471715336 Species 2 (S). Conc: 18.225756496514013
dynamics.set_chem_conc(species_name="U", conc=100.)
dynamics.describe_state()
SYSTEM STATE at Time t = 1.5: 3 species: Species 0 (U). Conc: 100.0 Species 1 (X). Conc: 37.298728471715336 Species 2 (S). Conc: 18.225756496514013
dynamics.get_history(tail=3)
| SYSTEM TIME | U | X | S | caption | |
|---|---|---|---|---|---|
| 281 | 1.49 | 72.224080 | 37.324855 | 18.226984 | |
| 282 | 1.50 | 72.237758 | 37.298728 | 18.225756 | |
| 283 | 1.50 | 100.000000 | 37.298728 | 18.225756 | Set concentration of `U` |
dynamics.single_compartment_react(time_step=0.01, stop_time=3.0,
dynamic_substeps=4, rel_fast_threshold=50)
df = dynamics.get_history()
#df
dynamics.explain_time_advance()
single_compartment_react(): setting abs_fast_threshold to 50.0 151 total step(s) taken From time 0 to 0.44, in 176 substeps of 0.0025 (each 1/4 of full step) From time 0.44 to 1.5, in 106 FULL steps of 0.01 From time 1.5 to 1.55, in 20 substeps of 0.0025 (each 1/4 of full step) From time 1.55 to 3.01, in 146 FULL steps of 0.01 (for a grand total of the equivalent of 301 FULL steps)
dynamics.plot_curves(colors=['green', 'orange', 'blue'])
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
2 S <-> U
Final concentrations: [U] = 93 ; [S] = 23.22
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 4.00501
Formula used: [U] / [S]
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 0.1252 %
Reaction IS in equilibrium (within 1% tolerance)
S <-> X
Final concentrations: [X] = 46.3 ; [S] = 23.22
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 1.99362
Formula used: [X] / [S]
2. Ratio of forward/reverse reaction rates: 2.0
Discrepancy between the two values: 0.3189 %
Reaction IS in equilibrium (within 1% tolerance)
True
dynamics.describe_state()
SYSTEM STATE at Time t = 3.01: 3 species: Species 0 (U). Conc: 93.00357364838469 Species 1 (X). Conc: 46.29552051953213 Species 2 (S). Conc: 23.221817151927773
dynamics.set_chem_conc(species_name="U", conc=150.)
dynamics.describe_state()
SYSTEM STATE at Time t = 3.01: 3 species: Species 0 (U). Conc: 150.0 Species 1 (X). Conc: 46.29552051953213 Species 2 (S). Conc: 23.221817151927773
dynamics.get_history(tail=3)
| SYSTEM TIME | U | X | S | caption | |
|---|---|---|---|---|---|
| 448 | 3.00 | 93.005965 | 46.290953 | 23.221603 | |
| 449 | 3.01 | 93.003574 | 46.295521 | 23.221817 | |
| 450 | 3.01 | 150.000000 | 46.295521 | 23.221817 | Set concentration of `U` |
dynamics.single_compartment_react(time_step=0.01, stop_time=4.5,
dynamic_substeps=4, rel_fast_threshold=50)
df = dynamics.history.get()
#df
dynamics.explain_time_advance()
single_compartment_react(): setting abs_fast_threshold to 50.0 150 total step(s) taken From time 0 to 0.44, in 176 substeps of 0.0025 (each 1/4 of full step) From time 0.44 to 1.5, in 106 FULL steps of 0.01 From time 1.5 to 1.55, in 20 substeps of 0.0025 (each 1/4 of full step) From time 1.55 to 3.01, in 146 FULL steps of 0.01 From time 3.01 to 3.16, in 60 substeps of 0.0025 (each 1/4 of full step) From time 3.16 to 4.51, in 135 FULL steps of 0.01 (for a grand total of the equivalent of 451 FULL steps)
dynamics.plot_curves(colors=['green', 'orange', 'blue'])
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium(explain=False)
True
dynamics.describe_state()
SYSTEM STATE at Time t = 4.51: 3 species: Species 0 (U). Conc: 134.56867943830346 Species 1 (X). Conc: 66.80533208508905 Species 2 (S). Conc: 33.57464670976427
dynamics.set_chem_conc(species_name="U", conc=80.)
dynamics.describe_state()
SYSTEM STATE at Time t = 4.51: 3 species: Species 0 (U). Conc: 80.0 Species 1 (X). Conc: 66.80533208508905 Species 2 (S). Conc: 33.57464670976427
dynamics.get_history(tail=3)
| SYSTEM TIME | U | X | S | caption | |
|---|---|---|---|---|---|
| 644 | 4.50 | 134.574232 | 66.794725 | 33.574148 | |
| 645 | 4.51 | 134.568679 | 66.805332 | 33.574647 | |
| 646 | 4.51 | 80.000000 | 66.805332 | 33.574647 | Set concentration of `U` |
dynamics.single_compartment_react(time_step=0.01, stop_time=6.,
dynamic_substeps=4, rel_fast_threshold=50)
df = dynamics.history.get()
#df
dynamics.explain_time_advance()
single_compartment_react(): setting abs_fast_threshold to 50.0 150 total step(s) taken From time 0 to 0.44, in 176 substeps of 0.0025 (each 1/4 of full step) From time 0.44 to 1.5, in 106 FULL steps of 0.01 From time 1.5 to 1.55, in 20 substeps of 0.0025 (each 1/4 of full step) From time 1.55 to 3.01, in 146 FULL steps of 0.01 From time 3.01 to 3.16, in 60 substeps of 0.0025 (each 1/4 of full step) From time 3.16 to 4.51, in 135 FULL steps of 0.01 From time 4.51 to 4.65, in 56 substeps of 0.0025 (each 1/4 of full step) From time 4.65 to 6.01, in 136 FULL steps of 0.01 (for a grand total of the equivalent of 601 FULL steps)
dynamics.plot_curves(colors=['green', 'orange', 'blue'])
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium(explain=False)
True
IDEAS TO EXPLORE:
Effect of the stoichiometry and the Delta_G on the "amplification" of the signal (from [U] to [X])
Effect of a continuously-varying (maybe oscillating [U]), and its being affected by the reactions' kinetics
Combining this experiment and up_regulate_2 in a "bifan motif"