A
up-regulates B
,¶A + X <-> 2B
(mostly forward), where X
is plentiful¶1st-order kinetics.
If [A] is low, [B] remains low, too. Then, if [A] goes high, then so does [B]. However, at that point, A can no longer bring B down to any substantial extent.
See also the experiment "1D/reactions/up_regulation_1"
LAST REVISED: May 26, 2024
import set_path # Importing this module will add the project's home directory to sys.path
Added 'D:\Docs\- MY CODE\BioSimulations\life123-Win7' to sys.path
from experiments.get_notebook_info import get_notebook_basename
from src.modules.chemicals.chem_data import ChemData as chem
from src.modules.reactions.reaction_dynamics import ReactionDynamics
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_2"],
extra_js="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.21.2/cytoscape.umd.js")
-> Output will be LOGGED into the file 'up_regulate_1.log.htm'
# Initialize the system
chem_data = chem(names=["A", "X", "B"])
# Reaction A + X <-> 2B , with 1st-order kinetics for all species
chem_data.add_reaction(reactants=["A" , "X"], products=[(2, "B", 1)],
forward_rate=8., reverse_rate=2.)
chem_data.describe_reactions()
# Send the plot of the reaction network to the HTML log file
chem_data.plot_reaction_network("vue_cytoscape_2")
Number of reactions: 1 (at temp. 25 C) 0: A + X <-> 2 B (kF = 8 / kR = 2 / delta_G = -3,436.6 / K = 4) | 1st order in all reactants & products Set of chemicals involved in the above reactions: {'A', 'B', 'X'} [GRAPHIC ELEMENT SENT TO LOG FILE `up_regulate_1.log.htm`]
dynamics = ReactionDynamics(chem_data=chem_data)
dynamics.set_conc(conc={"A": 5., "X": 100., "B": 0.},
snapshot=True) # A is scarce, X is plentiful, B is absent
dynamics.describe_state()
SYSTEM STATE at Time t = 0: 3 species: Species 0 (A). Conc: 5.0 Species 1 (X). Conc: 100.0 Species 2 (B). Conc: 0.0 Set of chemicals involved in reactions: {'A', 'B', 'X'}
dynamics.set_diagnostics() # To save diagnostic information about the call to single_compartment_react()
# This setting is a preset that can be adjusted make the time resolution finer or coarser;
# it will stay in effect from now on, unless explicitly changed later
dynamics.use_adaptive_preset(preset="fast")
dynamics.single_compartment_react(initial_step=0.0005, duration=0.015,
variable_steps=True, explain_variable_steps=False)
* INFO: the tentative time step (0.0005) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.0003) [Step started at t=0, and will rewind there] 27 total step(s) taken
dynamics.plot_history(colors=['red', 'darkorange', 'green'], show_intervals=True)
A, as the scarse limiting reagent, stops the reaction.
As long as A is low, B also remains low.
dynamics.get_history()
SYSTEM TIME | A | X | B | caption | |
---|---|---|---|---|---|
0 | 0.000000 | 5.000000 | 100.000000 | 0.000000 | Initial state |
1 | 0.000300 | 3.800000 | 98.800000 | 2.400000 | |
2 | 0.000600 | 2.900384 | 97.900384 | 4.199232 | |
3 | 0.000900 | 2.221427 | 97.221427 | 5.557147 | |
4 | 0.001200 | 1.706432 | 96.706432 | 6.587135 | |
5 | 0.001500 | 1.314329 | 96.314329 | 7.371341 | |
6 | 0.001800 | 1.014939 | 96.014939 | 7.970122 | |
7 | 0.002100 | 0.785843 | 95.785843 | 8.428314 | |
8 | 0.002400 | 0.610246 | 95.610246 | 8.779509 | |
9 | 0.002700 | 0.475484 | 95.475484 | 9.049033 | |
10 | 0.003000 | 0.371960 | 95.371960 | 9.256080 | |
11 | 0.003300 | 0.292375 | 95.292375 | 9.415250 | |
12 | 0.003600 | 0.231157 | 95.231157 | 9.537685 | |
13 | 0.003900 | 0.184048 | 95.184048 | 9.631904 | |
14 | 0.004200 | 0.147783 | 95.147783 | 9.704434 | |
15 | 0.004500 | 0.119859 | 95.119859 | 9.760283 | |
16 | 0.004800 | 0.098352 | 95.098352 | 9.803295 | |
17 | 0.005100 | 0.081787 | 95.081787 | 9.836426 | |
18 | 0.005400 | 0.069025 | 95.069025 | 9.861949 | |
19 | 0.005700 | 0.059193 | 95.059193 | 9.881614 | |
20 | 0.006150 | 0.047830 | 95.047830 | 9.904340 | |
21 | 0.006600 | 0.040378 | 95.040378 | 9.919244 | |
22 | 0.007050 | 0.035490 | 95.035490 | 9.929020 | |
23 | 0.007725 | 0.030681 | 95.030681 | 9.938638 | |
24 | 0.008737 | 0.027190 | 95.027190 | 9.945620 | |
25 | 0.010256 | 0.026007 | 95.026007 | 9.947986 | |
26 | 0.012534 | 0.026292 | 95.026292 | 9.947415 | |
27 | 0.015952 | 0.025975 | 95.025975 | 9.948051 |
dynamics.explain_time_advance()
From time 0 to 0.0057, in 19 steps of 0.0003 From time 0.0057 to 0.00705, in 3 steps of 0.00045 From time 0.00705 to 0.007725, in 1 step of 0.000675 From time 0.007725 to 0.008737, in 1 step of 0.00101 From time 0.008737 to 0.01026, in 1 step of 0.00152 From time 0.01026 to 0.01253, in 1 step of 0.00228 From time 0.01253 to 0.01595, in 1 step of 0.00342 (27 steps total)
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
0: A + X <-> 2 B Final concentrations: [A] = 0.02597 ; [B] = 9.948 ; [X] = 95.03 1. Ratio of reactant/product concentrations, adjusted for reaction orders: 4.03037 Formula used: [B] / ([A][X]) 2. Ratio of forward/reverse reaction rates: 4.0 Discrepancy between the two values: 0.7592 % Reaction IS in equilibrium (within 1% tolerance)
True
dynamics.set_single_conc(species_name="A", conc=50., snapshot=True)
dynamics.describe_state()
SYSTEM STATE at Time t = 0.015951562: 3 species: Species 0 (A). Conc: 50.0 Species 1 (X). Conc: 95.02597471866889 Species 2 (B). Conc: 9.948050562662225 Set of chemicals involved in reactions: {'A', 'B', 'X'}
dynamics.get_history(tail=5)
SYSTEM TIME | A | X | B | caption | |
---|---|---|---|---|---|
24 | 0.008737 | 0.027190 | 95.027190 | 9.945620 | |
25 | 0.010256 | 0.026007 | 95.026007 | 9.947986 | |
26 | 0.012534 | 0.026292 | 95.026292 | 9.947415 | |
27 | 0.015952 | 0.025975 | 95.025975 | 9.948051 | |
28 | 0.015952 | 50.000000 | 95.025975 | 9.948051 | Set concentration of `A` |
Notice the discontity in [A] in the last 2 rows
dynamics.single_compartment_react(initial_step=0.0005, target_end_time=0.035,
variable_steps=True, explain_variable_steps=False)
* INFO: the tentative time step (0.0005) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.0003) [Step started at t=0.015952, and will rewind there] * INFO: the tentative time step (0.0003) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.00018) [Step started at t=0.015952, and will rewind there] * INFO: the tentative time step (0.00018) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.000108) [Step started at t=0.015952, and will rewind there] * INFO: the tentative time step (0.000108) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 6.48e-05) [Step started at t=0.015952, and will rewind there] * INFO: the tentative time step (6.48e-05) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 3.888e-05) [Step started at t=0.015952, and will rewind there] Some steps were backtracked and re-done, to prevent negative concentrations or excessively large concentration changes 51 total step(s) taken
dynamics.plot_history(colors=['red', 'darkorange', 'green'], show_intervals=True)
A
, still the limiting reagent, is again eventually stopping the reaction...
The (transiently) high value of [A] led to a high value of [B]
Notice how the variable time steps automatically adapt.
#dynamics.get_history()
#dynamics.explain_time_advance()
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
0: A + X <-> 2 B Final concentrations: [A] = 0.5992 ; [B] = 108.7 ; [X] = 45.63 1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.97761 Formula used: [B] / ([A][X]) 2. Ratio of forward/reverse reaction rates: 4.0 Discrepancy between the two values: 0.5598 % Reaction IS in equilibrium (within 1% tolerance)
True
dynamics.set_single_conc(species_name="A", conc=30., snapshot=True)
dynamics.describe_state()
SYSTEM STATE at Time t = 0.039055056: 3 species: Species 0 (A). Conc: 30.0 Species 1 (X). Conc: 45.62521424281943 Species 2 (B). Conc: 108.74957151436116 Set of chemicals involved in reactions: {'A', 'B', 'X'}
dynamics.get_history(tail=5)
SYSTEM TIME | A | X | B | caption | |
---|---|---|---|---|---|
76 | 0.028635 | 0.690343 | 45.716318 | 108.567364 | |
77 | 0.030829 | 0.612807 | 45.638782 | 108.722436 | |
78 | 0.034119 | 0.592086 | 45.618060 | 108.763879 | |
79 | 0.039055 | 0.599240 | 45.625214 | 108.749572 | |
80 | 0.039055 | 30.000000 | 45.625214 | 108.749572 | Set concentration of `A` |
dynamics.single_compartment_react(initial_step=0.0005, target_end_time=0.070,
variable_steps=True, explain_variable_steps=False)
* INFO: the tentative time step (0.0005) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.0003) [Step started at t=0.039055, and will rewind there] * INFO: the tentative time step (0.0003) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.00018) [Step started at t=0.039055, and will rewind there] * INFO: the tentative time step (0.00018) leads to a least one norm value > its ABORT threshold: -> will backtrack, and re-do step with a SMALLER delta time, multiplied by 0.6 (set to 0.000108) [Step started at t=0.039055, and will rewind there] 28 total step(s) taken
dynamics.plot_history(colors=['red', 'darkorange', 'green'], show_intervals=True)
A
, again the scarce limiting reagent, stops the reaction yet again.
And, again, the (transiently) high value of [A] up-regulated [B]
Notes:
A
can up-regulate B
, but it cannot bring it down.
X
will soon need to be replenished, if A
is to continue being the limiting reagent.**
# Zoom in on the early part of the last plot
dynamics.plot_history(colors=['red', 'darkorange', 'green'], xrange=[0, 0.02])
# Look up the first intersection of the [A] and [B] curves
dynamics.curve_intersect("A", "B", t_start=0, t_end=0.01)
(0.00045562195425603814, 3.333333333333333)
# The next intersection isn't particulary meaning; just an artifact of the sudden jump in [A]
dynamics.curve_intersect("A", "B", t_start=0.01, t_end=0.02)
WARNING: curve_intersect(): Discontinuity detected at `SYSTEM TIME` = 0.015951562499999995
(0.015951562499999995, 9.948050562662225)
# The final intersection
dynamics.curve_intersect("A", "B", t_start=0.016, t_end=0.02)
(0.01638486713665179, 36.649350187554084)
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
0: A + X <-> 2 B Final concentrations: [A] = 2.284 ; [B] = 164.2 ; [X] = 17.91 1. Ratio of reactant/product concentrations, adjusted for reaction orders: 4.01395 Formula used: [B] / ([A][X]) 2. Ratio of forward/reverse reaction rates: 4.0 Discrepancy between the two values: 0.3487 % Reaction IS in equilibrium (within 1% tolerance)
True