A up-regulates B , by being the limiting reagent in the reaction:¶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.
Single-bin reaction
Based on experiment reactions_single_compartment/up_regulate_1
LAST_REVISED = "May 5, 2025"
LIFE123_VERSION = "1.0.0rc3" # Library version this experiment is based on
#import set_path # Using MyBinder? Uncomment this before running the next cell!
#import sys
#sys.path.append("C:/some_path/my_env_or_install") # CHANGE to the folder containing your venv or libraries installation!
# NOTE: If any of the imports below can't find a module, uncomment the lines above, or try: import set_path
from experiments.get_notebook_info import get_notebook_basename
from life123 import check_version, ChemData, BioSim1D, 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_regulation_1.log.htm'
# Initialize the system. NOTE: Diffusion not applicable (just 1 bin)
chem_data = ChemData(names=["A", "X", "B"], plot_colors=['red', 'darkorange', 'green'])
bio = BioSim1D(n_bins=1, chem_data=chem_data)
bio.set_uniform_concentration(chem_label="A", conc=5.) # Scarce
bio.set_uniform_concentration(chem_label="X", conc=100.) # Plentiful
# Initially, no "B" is present
bio.describe_state()
SYSTEM STATE at Time t = 0: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 5.0 |
| 1 | X | None | 100.0 |
| 2 | B | None | 0.0 |
reactions = bio.get_reactions()
# Reaction A + X <-> 2B , with 1st-order kinetics for all species
reactions.add_reaction(reactants=["A" , "X"], products=[(2, "B", 1)],
forward_rate=8., reverse_rate=2.)
reactions.describe_reactions()
# Send the plot of the reaction network to the HTML log file
reactions.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: {"B" (green), "X" (darkorange), "A" (red)}
[GRAPHIC ELEMENT SENT TO LOG FILE `up_regulation_1.log.htm`]
# Let's enable history for all the chemicals
bio.enable_history(take_snapshot=True) # Taking a snapshot to include the current initial state in the history
History enabled for bins None and chemicals None (None means 'all')
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0 | 5.0 | 100.0 | 0.0 |
bio.react(time_step=0.0005, n_steps=30)
bio.describe_state()
System Time is now: 0.015 SYSTEM STATE at Time t = 0.015: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 0.026173 |
| 1 | X | None | 95.026173 |
| 2 | B | None | 9.947653 |
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0000 | 5.000000 | 100.000000 | 0.000000 | |
| 1 | 0.0005 | 3.000000 | 98.000000 | 4.000000 | |
| 2 | 0.0010 | 1.828000 | 96.828000 | 6.344000 | |
| 3 | 0.0015 | 1.126338 | 96.126338 | 7.747325 | |
| 4 | 0.0020 | 0.701002 | 95.701002 | 8.597996 | |
| 5 | 0.0025 | 0.441254 | 95.441254 | 9.117493 | |
| 6 | 0.0030 | 0.281916 | 95.281916 | 9.436168 | |
| 7 | 0.0035 | 0.183906 | 95.183906 | 9.632188 | |
| 8 | 0.0040 | 0.123519 | 95.123519 | 9.752963 | |
| 9 | 0.0045 | 0.086274 | 95.086274 | 9.827453 | |
| 10 | 0.0050 | 0.063287 | 95.063287 | 9.873425 | |
| 11 | 0.0055 | 0.049096 | 95.049096 | 9.901809 | |
| 12 | 0.0060 | 0.040331 | 95.040331 | 9.919337 | |
| 13 | 0.0065 | 0.034918 | 95.034918 | 9.930163 | |
| 14 | 0.0070 | 0.031575 | 95.031575 | 9.936851 | |
| 15 | 0.0075 | 0.029509 | 95.029509 | 9.940982 | |
| 16 | 0.0080 | 0.028233 | 95.028233 | 9.943534 | |
| 17 | 0.0085 | 0.027445 | 95.027445 | 9.945110 | |
| 18 | 0.0090 | 0.026958 | 95.026958 | 9.946084 | |
| 19 | 0.0095 | 0.026657 | 95.026657 | 9.946686 | |
| 20 | 0.0100 | 0.026471 | 95.026471 | 9.947058 | |
| 21 | 0.0105 | 0.026356 | 95.026356 | 9.947287 | |
| 22 | 0.0110 | 0.026285 | 95.026285 | 9.947429 | |
| 23 | 0.0115 | 0.026242 | 95.026242 | 9.947517 | |
| 24 | 0.0120 | 0.026215 | 95.026215 | 9.947571 | |
| 25 | 0.0125 | 0.026198 | 95.026198 | 9.947604 | |
| 26 | 0.0130 | 0.026188 | 95.026188 | 9.947625 | |
| 27 | 0.0135 | 0.026181 | 95.026181 | 9.947638 | |
| 28 | 0.0140 | 0.026177 | 95.026177 | 9.947646 | |
| 29 | 0.0145 | 0.026175 | 95.026175 | 9.947650 | |
| 30 | 0.0150 | 0.026173 | 95.026173 | 9.947653 |
A, as the scarse limiting reagent, stops the reaction.
When A is low, B is also low.
Consistent with the 4/1 ratio of forward/reverse rates (and the 1st order reactions), the systems settles in the following equilibrium:
# Verify that the reaction has reached equilibrium
bio.reaction_dynamics.is_in_equilibrium(rxn_index=0, conc=bio.bin_snapshot(bin_address = 0))
A + X <-> 2 B
Current concentrations: [A] = 0.02617 ; [X] = 95.03 ; [B] = 9.948
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.99963
Formula used: [B] / ([A][X])
2. Ratio of forward/reverse reaction rates: 4
Discrepancy between the two values: 0.009347 %
Reaction IS in equilibrium (within 1% tolerance)
True
bio.plot_history_single_bin(bin_address=0,
title_prefix="Reaction A + X <-> 2B")
bio.set_bin_conc(bin_address=0, chem_index=0, conc=50.)
bio.describe_state()
SYSTEM STATE at Time t = 0.015: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 50.000000 |
| 1 | X | None | 95.026173 |
| 2 | B | None | 9.947653 |
bio.capture_snapshot(caption="[A] suddenly increased externally")
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0000 | 5.000000 | 100.000000 | 0.000000 | |
| 1 | 0.0005 | 3.000000 | 98.000000 | 4.000000 | |
| 2 | 0.0010 | 1.828000 | 96.828000 | 6.344000 | |
| 3 | 0.0015 | 1.126338 | 96.126338 | 7.747325 | |
| 4 | 0.0020 | 0.701002 | 95.701002 | 8.597996 | |
| 5 | 0.0025 | 0.441254 | 95.441254 | 9.117493 | |
| 6 | 0.0030 | 0.281916 | 95.281916 | 9.436168 | |
| 7 | 0.0035 | 0.183906 | 95.183906 | 9.632188 | |
| 8 | 0.0040 | 0.123519 | 95.123519 | 9.752963 | |
| 9 | 0.0045 | 0.086274 | 95.086274 | 9.827453 | |
| 10 | 0.0050 | 0.063287 | 95.063287 | 9.873425 | |
| 11 | 0.0055 | 0.049096 | 95.049096 | 9.901809 | |
| 12 | 0.0060 | 0.040331 | 95.040331 | 9.919337 | |
| 13 | 0.0065 | 0.034918 | 95.034918 | 9.930163 | |
| 14 | 0.0070 | 0.031575 | 95.031575 | 9.936851 | |
| 15 | 0.0075 | 0.029509 | 95.029509 | 9.940982 | |
| 16 | 0.0080 | 0.028233 | 95.028233 | 9.943534 | |
| 17 | 0.0085 | 0.027445 | 95.027445 | 9.945110 | |
| 18 | 0.0090 | 0.026958 | 95.026958 | 9.946084 | |
| 19 | 0.0095 | 0.026657 | 95.026657 | 9.946686 | |
| 20 | 0.0100 | 0.026471 | 95.026471 | 9.947058 | |
| 21 | 0.0105 | 0.026356 | 95.026356 | 9.947287 | |
| 22 | 0.0110 | 0.026285 | 95.026285 | 9.947429 | |
| 23 | 0.0115 | 0.026242 | 95.026242 | 9.947517 | |
| 24 | 0.0120 | 0.026215 | 95.026215 | 9.947571 | |
| 25 | 0.0125 | 0.026198 | 95.026198 | 9.947604 | |
| 26 | 0.0130 | 0.026188 | 95.026188 | 9.947625 | |
| 27 | 0.0135 | 0.026181 | 95.026181 | 9.947638 | |
| 28 | 0.0140 | 0.026177 | 95.026177 | 9.947646 | |
| 29 | 0.0145 | 0.026175 | 95.026175 | 9.947650 | |
| 30 | 0.0150 | 0.026173 | 95.026173 | 9.947653 | |
| 31 | 0.0150 | 50.000000 | 95.026173 | 9.947653 | [A] suddenly increased externally |
bio.react(time_step=0.0005, n_steps=40)
bio.describe_state()
System Time is now: 0.035 SYSTEM STATE at Time t = 0.035: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 0.601080 |
| 1 | X | None | 45.627253 |
| 2 | B | None | 108.745494 |
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0000 | 5.000000 | 100.000000 | 0.000000 | |
| 1 | 0.0005 | 3.000000 | 98.000000 | 4.000000 | |
| 2 | 0.0010 | 1.828000 | 96.828000 | 6.344000 | |
| 3 | 0.0015 | 1.126338 | 96.126338 | 7.747325 | |
| 4 | 0.0020 | 0.701002 | 95.701002 | 8.597996 | |
| ... | ... | ... | ... | ... | ... |
| 67 | 0.0330 | 0.607674 | 45.633847 | 108.732305 | |
| 68 | 0.0335 | 0.605484 | 45.631658 | 108.736685 | |
| 69 | 0.0340 | 0.603704 | 45.629877 | 108.740246 | |
| 70 | 0.0345 | 0.602256 | 45.628430 | 108.743141 | |
| 71 | 0.0350 | 0.601080 | 45.627253 | 108.745494 |
72 rows × 5 columns
A, still the limiting reagent, is again stopping the reaction.
The (transiently) high value of [A] led to a high value of [B]
# Verify the equilibrium
bio.reaction_dynamics.is_in_equilibrium(rxn_index=0, conc=bio.bin_snapshot(bin_address = 0))
Ratio of equilibrium concentrations (B_eq / (A_eq * X_eq)): 3.9999999999983915
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[24], line 6 4 B_eq = bio.bin_concentration(0, 2) 5 print("Ratio of equilibrium concentrations (B_eq / (A_eq * X_eq)): ", (B_eq / (A_eq * X_eq))) ----> 6 print("Ratio of forward/reverse rates: ", chem_data.get_forward_rate(0) / chem_data.get_reverse_rate(0)) AttributeError: 'ChemData' object has no attribute 'get_forward_rate'
bio.plot_history_single_bin(bin_address=0,
title_prefix="Reaction A + X <-> 2B")
A, still the limiting reagent, is again stopping the reaction.
The (transiently) high value of [A] led to a high value of [B]
bio.set_bin_conc(bin_address=0, chem_index=0, conc=30.)
bio.describe_state()
SYSTEM STATE at Time t = 0.035: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 30.000000 |
| 1 | X | None | 45.627253 |
| 2 | B | None | 108.745494 |
bio.capture_snapshot(caption="[A] again suddenly increased externally")
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0000 | 5.000000 | 100.000000 | 0.000000 | |
| 1 | 0.0005 | 3.000000 | 98.000000 | 4.000000 | |
| 2 | 0.0010 | 1.828000 | 96.828000 | 6.344000 | |
| 3 | 0.0015 | 1.126338 | 96.126338 | 7.747325 | |
| 4 | 0.0020 | 0.701002 | 95.701002 | 8.597996 | |
| ... | ... | ... | ... | ... | ... |
| 68 | 0.0335 | 0.605484 | 45.631658 | 108.736685 | |
| 69 | 0.0340 | 0.603704 | 45.629877 | 108.740246 | |
| 70 | 0.0345 | 0.602256 | 45.628430 | 108.743141 | |
| 71 | 0.0350 | 0.601080 | 45.627253 | 108.745494 | |
| 72 | 0.0350 | 30.000000 | 45.627253 | 108.745494 | [A] again suddenly increased externally |
73 rows × 5 columns
bio.react(time_step=0.0005, n_steps=70)
bio.describe_state()
System Time is now: 0.07 SYSTEM STATE at Time t = 0.07: 1 bins and 3 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 2.316313 |
| 1 | X | None | 17.943565 |
| 2 | B | None | 164.112869 |
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | X | B | caption | |
|---|---|---|---|---|---|
| 0 | 0.0000 | 5.000000 | 100.000000 | 0.000000 | |
| 1 | 0.0005 | 3.000000 | 98.000000 | 4.000000 | |
| 2 | 0.0010 | 1.828000 | 96.828000 | 6.344000 | |
| 3 | 0.0015 | 1.126338 | 96.126338 | 7.747325 | |
| 4 | 0.0020 | 0.701002 | 95.701002 | 8.597996 | |
| ... | ... | ... | ... | ... | ... |
| 138 | 0.0680 | 2.326989 | 17.954242 | 164.091517 | |
| 139 | 0.0685 | 2.323963 | 17.951216 | 164.097568 | |
| 140 | 0.0690 | 2.321189 | 17.948442 | 164.103117 | |
| 141 | 0.0695 | 2.318645 | 17.945898 | 164.108204 | |
| 142 | 0.0700 | 2.316313 | 17.943565 | 164.112869 |
143 rows × 5 columns
A, again the scarse limiting reagent, stops the reaction yet again
# Verify the equilibrium
bio.reaction_dynamics.is_in_equilibrium(conc=bio.bin_snapshot(bin_address = 0),
tolerance=2)
0: A + X <-> 2 B
Current concentrations: [A] = 2.316 ; [X] = 17.94 ; [B] = 164.1
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 3.94854
Formula used: [B] / ([A][X])
2. Ratio of forward/reverse reaction rates: 4
Discrepancy between the two values: 1.286 %
Reaction IS in equilibrium (within 2% tolerance)
True
bio.plot_history_single_bin(bin_address=0,
title_prefix="Reaction A + X <-> 2B")
A, again the scarse limiting reagent, stops the reaction yet again.
And, again, the (transiently) high value of [A] up-regulated [B]
Note: 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.
reactions_single_compartment/up_regulate_1¶