A down-regulates B ,¶A + 2 B <-> Y (mostly forward)¶1st-order kinetics.
If [A] is low and [B] is high, then [B] remains high. If [A] goes high, [B] goes low. However, at that point, A can no longer bring B up to any substantial extent.
See also 1D/reactions/down_regulation_1
LAST REVISED: Feb. 5, 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 'down_regulate_2.log.htm'
# Initialize the system
chem_data = chem(names=["A", "B", "Y"])
# Reaction A + 2 B <-> Y , with 1st-order kinetics for all species
chem_data.add_reaction(reactants=[("A") , (2, "B")], products=[("Y")],
forward_rate=8., reverse_rate=2.)
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: 1 (at temp. 25 C) 0: A + 2 B <-> Y (kF = 8 / kR = 2 / Delta_G = -3,436.56 / K = 4) | 1st order in all reactants & products [GRAPHIC ELEMENT SENT TO LOG FILE `down_regulate_2.log.htm`]
dynamics = ReactionDynamics(reaction_data=chem_data)
dynamics.set_conc(conc={"A": 5., "B": 100., "Y": 0.},
snapshot=True) # A is scarce, B is plentiful, Y is absent
dynamics.describe_state()
SYSTEM STATE at Time t = 0: 3 species: Species 0 (A). Conc: 5.0 Species 1 (B). Conc: 100.0 Species 2 (Y). Conc: 0.0
dynamics.single_compartment_react(time_step=0.0005, n_steps=30,
dynamic_substeps=2, rel_fast_threshold=15)
df = dynamics.get_history()
df
single_compartment_react(): setting abs_fast_threshold to 300.0 30 total step(s) taken
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 0 | 0.00000 | 5.000000 | 100.000000 | 0.000000 | Initial state |
| 1 | 0.00025 | 4.000000 | 98.000000 | 1.000000 | Interm. step, due to the fast rxns: [0] |
| 2 | 0.00050 | 3.216500 | 96.433000 | 1.783500 | |
| 3 | 0.00075 | 2.597038 | 95.194077 | 2.402962 | Interm. step, due to the fast rxns: [0] |
| 4 | 0.00100 | 2.103794 | 94.207589 | 2.896206 | |
| 5 | 0.00125 | 1.708856 | 93.417711 | 3.291144 | Interm. step, due to the fast rxns: [0] |
| 6 | 0.00150 | 1.391227 | 92.782453 | 3.608773 | |
| 7 | 0.00175 | 1.134868 | 92.269736 | 3.865132 | Interm. step, due to the fast rxns: [0] |
| 8 | 0.00200 | 0.927373 | 91.854745 | 4.072627 | |
| 9 | 0.00225 | 0.759042 | 91.518084 | 4.240958 | Interm. step, due to the fast rxns: [0] |
| 10 | 0.00250 | 0.622230 | 91.244460 | 4.377770 | |
| 11 | 0.00275 | 0.510869 | 91.021738 | 4.489131 | Interm. step, due to the fast rxns: [0] |
| 12 | 0.00300 | 0.420113 | 90.840226 | 4.579887 | |
| 13 | 0.00325 | 0.346077 | 90.692154 | 4.653923 | Interm. step, due to the fast rxns: [0] |
| 14 | 0.00350 | 0.285631 | 90.571262 | 4.714369 | |
| 15 | 0.00375 | 0.236248 | 90.472496 | 4.763752 | Interm. step, due to the fast rxns: [0] |
| 16 | 0.00400 | 0.195882 | 90.391764 | 4.804118 | |
| 17 | 0.00425 | 0.162872 | 90.325744 | 4.837128 | Interm. step, due to the fast rxns: [0] |
| 18 | 0.00450 | 0.135867 | 90.271735 | 4.864133 | |
| 19 | 0.00500 | 0.091672 | 90.183343 | 4.908328 | |
| 20 | 0.00550 | 0.063511 | 90.127022 | 4.936489 | |
| 21 | 0.00600 | 0.045551 | 90.091102 | 4.954449 | |
| 22 | 0.00650 | 0.034091 | 90.068181 | 4.965909 | |
| 23 | 0.00700 | 0.026775 | 90.053549 | 4.973225 | |
| 24 | 0.00750 | 0.022103 | 90.044206 | 4.977897 | |
| 25 | 0.00800 | 0.019120 | 90.038240 | 4.980880 | |
| 26 | 0.00850 | 0.017215 | 90.034430 | 4.982785 | |
| 27 | 0.00900 | 0.015998 | 90.031996 | 4.984002 | |
| 28 | 0.00950 | 0.015221 | 90.030441 | 4.984779 | |
| 29 | 0.01000 | 0.014724 | 90.029448 | 4.985276 | |
| 30 | 0.01050 | 0.014407 | 90.028814 | 4.985593 | |
| 31 | 0.01100 | 0.014204 | 90.028409 | 4.985796 | |
| 32 | 0.01150 | 0.014075 | 90.028150 | 4.985925 | |
| 33 | 0.01200 | 0.013992 | 90.027985 | 4.986008 | |
| 34 | 0.01250 | 0.013940 | 90.027879 | 4.986060 | |
| 35 | 0.01300 | 0.013906 | 90.027812 | 4.986094 | |
| 36 | 0.01350 | 0.013884 | 90.027769 | 4.986116 | |
| 37 | 0.01400 | 0.013871 | 90.027741 | 4.986129 | |
| 38 | 0.01450 | 0.013862 | 90.027723 | 4.986138 | |
| 39 | 0.01500 | 0.013856 | 90.027712 | 4.986144 |
A, as the scarse limiting reagent, stops the reaction.
When A is low, B is also low.
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
A + 2 B <-> Y
Final concentrations: [Y] = 4.986 ; [A] = 0.01386 ; [B] = 90.03
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.99712
Formula used: [Y] / ([A][B])
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 0.07189 %
Reaction IS in equilibrium (within 1% tolerance)
True
dynamics.plot_curves(colors=['red', 'darkorange', 'green'],
title="Changes in concentrations (reaction A + 2 B <-> Y)")
dynamics.set_chem_conc(species_name="A", conc=40., snapshot=True)
dynamics.describe_state()
SYSTEM STATE at Time t = 0.015: 3 species: Species 0 (A). Conc: 40.0 Species 1 (B). Conc: 90.0277121942094 Species 2 (Y). Conc: 4.986143902895314
dynamics.history.get(tail=5)
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 36 | 0.0135 | 0.013884 | 90.027769 | 4.986116 | |
| 37 | 0.0140 | 0.013871 | 90.027741 | 4.986129 | |
| 38 | 0.0145 | 0.013862 | 90.027723 | 4.986138 | |
| 39 | 0.0150 | 0.013856 | 90.027712 | 4.986144 | |
| 40 | 0.0150 | 40.000000 | 90.027712 | 4.986144 | Set concentration of `A` |
dynamics.single_compartment_react(time_step=0.001, n_steps=40,
dynamic_substeps=2, rel_fast_threshold=15)
df = dynamics.history.get()
df
single_compartment_react(): setting abs_fast_threshold to 150.0 40 total step(s) taken
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 0 | 0.00000 | 5.000000 | 100.000000 | 0.000000 | Initial state |
| 1 | 0.00025 | 4.000000 | 98.000000 | 1.000000 | Interm. step, due to the fast rxns: [0] |
| 2 | 0.00050 | 3.216500 | 96.433000 | 1.783500 | |
| 3 | 0.00075 | 2.597038 | 95.194077 | 2.402962 | Interm. step, due to the fast rxns: [0] |
| 4 | 0.00100 | 2.103794 | 94.207589 | 2.896206 | |
| ... | ... | ... | ... | ... | ... |
| 96 | 0.05100 | 1.006306 | 12.040324 | 43.979838 | |
| 97 | 0.05200 | 0.997335 | 12.022383 | 43.988808 | |
| 98 | 0.05300 | 0.989390 | 12.006493 | 43.996754 | |
| 99 | 0.05400 | 0.982351 | 11.992414 | 44.003793 | |
| 100 | 0.05500 | 0.976112 | 11.979937 | 44.010031 |
101 rows × 5 columns
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium(tolerance=6)
A + 2 B <-> Y
Final concentrations: [Y] = 44.01 ; [A] = 0.9761 ; [B] = 11.98
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.76355
Formula used: [Y] / ([A][B])
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 5.911 %
Reaction IS in equilibrium (within 6% tolerance)
True
dynamics.plot_curves(colors=['red', 'darkorange', 'green'],
title="Changes in concentrations (reaction A + 2 B <-> Y)")
A, still the limiting reagent, is again stopping the reaction.
The (transiently) high value of [A] led to a high value of [B]
dynamics.set_chem_conc(species_name="A", conc=30., snapshot=True)
dynamics.describe_state()
SYSTEM STATE at Time t = 0.055: 3 species: Species 0 (A). Conc: 30.0 Species 1 (B). Conc: 11.979937031950595 Species 2 (Y). Conc: 44.010031484024715
dynamics.history.get(tail=5)
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 97 | 0.052 | 0.997335 | 12.022383 | 43.988808 | |
| 98 | 0.053 | 0.989390 | 12.006493 | 43.996754 | |
| 99 | 0.054 | 0.982351 | 11.992414 | 44.003793 | |
| 100 | 0.055 | 0.976112 | 11.979937 | 44.010031 | |
| 101 | 0.055 | 30.000000 | 11.979937 | 44.010031 | Set concentration of `A` |
dynamics.single_compartment_react(time_step=0.001, n_steps=35,
dynamic_substeps=2, rel_fast_threshold=15)
df = dynamics.get_history()
df
single_compartment_react(): setting abs_fast_threshold to 150.0 35 total step(s) taken
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 0 | 0.00000 | 5.000000 | 100.000000 | 0.000000 | Initial state |
| 1 | 0.00025 | 4.000000 | 98.000000 | 1.000000 | Interm. step, due to the fast rxns: [0] |
| 2 | 0.00050 | 3.216500 | 96.433000 | 1.783500 | |
| 3 | 0.00075 | 2.597038 | 95.194077 | 2.402962 | Interm. step, due to the fast rxns: [0] |
| 4 | 0.00100 | 2.103794 | 94.207589 | 2.896206 | |
| ... | ... | ... | ... | ... | ... |
| 140 | 0.08600 | 24.266272 | 0.512481 | 49.743760 | |
| 141 | 0.08700 | 24.266271 | 0.512480 | 49.743760 | |
| 142 | 0.08800 | 24.266271 | 0.512479 | 49.743760 | |
| 143 | 0.08900 | 24.266271 | 0.512479 | 49.743761 | |
| 144 | 0.09000 | 24.266271 | 0.512479 | 49.743761 |
145 rows × 5 columns
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium()
A + 2 B <-> Y
Final concentrations: [Y] = 49.74 ; [A] = 24.27 ; [B] = 0.5125
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 4
Formula used: [Y] / ([A][B])
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 6.852e-05 %
Reaction IS in equilibrium (within 1% tolerance)
True
dynamics.plot_curves(colors=['red', 'darkorange', 'green'],
title="Changes in concentrations (reaction A + 2 B <-> Y)")
A, again the scarse limiting reagent, stops the reaction yet again
dynamics.set_chem_conc(species_name="A", conc=0., snapshot=True) # Completely eliminate A
dynamics.describe_state()
SYSTEM STATE at Time t = 0.09: 3 species: Species 0 (A). Conc: 0.0 Species 1 (B). Conc: 0.5124787710943272 Species 2 (Y). Conc: 49.74376061445283
dynamics.single_compartment_react(time_step=0.001, n_steps=70,
dynamic_substeps=2, rel_fast_threshold=15)
dynamics.get_history()
single_compartment_react(): setting abs_fast_threshold to 150.0 70 total step(s) taken
| SYSTEM TIME | A | B | Y | caption | |
|---|---|---|---|---|---|
| 0 | 0.00000 | 5.000000 | 100.000000 | 0.000000 | Initial state |
| 1 | 0.00025 | 4.000000 | 98.000000 | 1.000000 | Interm. step, due to the fast rxns: [0] |
| 2 | 0.00050 | 3.216500 | 96.433000 | 1.783500 | |
| 3 | 0.00075 | 2.597038 | 95.194077 | 2.402962 | Interm. step, due to the fast rxns: [0] |
| 4 | 0.00100 | 2.103794 | 94.207589 | 2.896206 | |
| ... | ... | ... | ... | ... | ... |
| 224 | 0.15600 | 2.291779 | 5.096036 | 47.451982 | |
| 225 | 0.15700 | 2.293251 | 5.098980 | 47.450510 | |
| 226 | 0.15800 | 2.294606 | 5.101691 | 47.449155 | |
| 227 | 0.15900 | 2.295853 | 5.104185 | 47.447907 | |
| 228 | 0.16000 | 2.297001 | 5.106481 | 47.446759 |
229 rows × 5 columns
# Verify that the reaction has reached equilibrium
dynamics.is_in_equilibrium(tolerance=2)
A + 2 B <-> Y
Final concentrations: [Y] = 47.45 ; [A] = 2.297 ; [B] = 5.106
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 4.04505
Formula used: [Y] / ([A][B])
2. Ratio of forward/reverse reaction rates: 4.0
Discrepancy between the two values: 1.126 %
Reaction IS in equilibrium (within 2% tolerance)
True
dynamics.plot_curves(colors=['red', 'darkorange', 'green'],
title="Changes in concentrations (reaction A + 2 B <-> Y)")
Le Chatelier's principle in action: "A change in one of the variables that describe a system at equilibrium produces a shift in the position of the equilibrium that counteracts the effect of this change."