LAST_REVISED = "May 4, 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, os
#os.getcwd()
#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 ChemData, BioSim1D, check_version
from life123 import GraphicLog
check_version(LIFE123_VERSION)
OK
# 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 'reaction_2.log.htm'
# Initialize the system
chem_data = ChemData(names=["A", "B"]) # NOTE: Diffusion not applicable (just 1 bin)
bio = BioSim1D(n_bins=1, chem_data=chem_data)
bio.set_uniform_concentration(chem_index=0, conc=10.)
bio.set_uniform_concentration(chem_index=1, conc=50.)
bio.describe_state()
SYSTEM STATE at Time t = 0: 1 bins and 2 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 10.0 |
| 1 | B | None | 50.0 |
# Specify the reaction
reactions = bio.get_reactions()
# Reaction A <-> 3B , with 1st-order kinetics in both directions
reactions.add_reaction(reactants="A", products=[(3,"B",1)], forward_rate=5., reverse_rate=2.)
reactions.describe_reactions()
Number of reactions: 1 (at temp. 25 C)
0: A <-> 3 B (kF = 5 / kR = 2 / delta_G = -2,271.4 / K = 2.5) | 1st order in all reactants & products
Set of chemicals involved in the above reactions: {'B', 'A'}
# Send the plot of the reaction network to the HTML log file
reactions.plot_reaction_network("vue_cytoscape_2")
[GRAPHIC ELEMENT SENT TO LOG FILE `reaction_2.log.htm`]
# Let's enable history - by default for all chemicals and all bins
bio.enable_history(take_snapshot=True, caption="Initial state")
History enabled for bins None and chemicals None (None means 'all')
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | B | caption | |
|---|---|---|---|---|
| 0 | 0.0 | 10.0 | 50.0 | Initial state |
# First step
bio.react(time_step=0.1, n_steps=1)
bio.describe_state()
System Time is now: 0.1 SYSTEM STATE at Time t = 0.1: 1 bins and 2 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 15.0 |
| 1 | B | None | 35.0 |
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | B | caption | |
|---|---|---|---|---|
| 0 | 0.0 | 10.0 | 50.0 | Initial state |
| 1 | 0.1 | 15.0 | 35.0 |
# Numerous more steps
bio.react(time_step=0.1, n_steps=10)
bio.describe_state()
System Time is now: 1.1 SYSTEM STATE at Time t = 1.1: 1 bins and 2 chemical species:
| Species | Diff rate | Bin 0 | |
|---|---|---|---|
| 0 | A | None | 14.545455 |
| 1 | B | None | 36.363636 |
Consistent with the 5/2 ratio of forward/reverse rates (and the 1st order reactions), the systems settles in the equilibrium: [A] = 14.54545455 , [B] = 36.36363636
# Verify that the reaction has reached equilibrium
bio.reaction_dynamics.is_in_equilibrium(conc=bio.bin_snapshot(bin_address = 0))
0: A <-> 3 B
Current concentrations: [A] = 14.55 ; [B] = 36.36
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 2.5
Formula used: [B] / [A]
2. Ratio of forward/reverse reaction rates: 2.5
Discrepancy between the two values: 6.875e-10 %
Reaction IS in equilibrium (within 1% tolerance)
True
bio.get_bin_history(bin_address=0)
| SYSTEM TIME | A | B | caption | |
|---|---|---|---|---|
| 0 | 0.0 | 10.000000 | 50.000000 | Initial state |
| 1 | 0.1 | 15.000000 | 35.000000 | |
| 2 | 0.2 | 14.500000 | 36.500000 | |
| 3 | 0.3 | 14.550000 | 36.350000 | |
| 4 | 0.4 | 14.545000 | 36.365000 | |
| 5 | 0.5 | 14.545500 | 36.363500 | |
| 6 | 0.6 | 14.545450 | 36.363650 | |
| 7 | 0.7 | 14.545455 | 36.363635 | |
| 8 | 0.8 | 14.545454 | 36.363637 | |
| 9 | 0.9 | 14.545455 | 36.363636 | |
| 10 | 1.0 | 14.545455 | 36.363636 | |
| 11 | 1.1 | 14.545455 | 36.363636 |
Note how the simulation initially OVERSHOT the equilibrium values; the first step was too large!
bio.plot_history_single_bin(bin_address=0,
title="Reaction A <-> B . Concentrations at bin 0")
# Same plot, but with smooth line
bio.plot_history_single_bin(bin_address=0,
title="Reaction A <-> B . Concentrations at bin 0",
smoothed=True)
The early OVERSHOOTING of the equilibrium values shows prominently in the last plot!