LAST_REVISED = "Jan. 4, 2026"
LIFE123_VERSION = "1.0.0rc7" # 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
import pandas as pd
from life123 import check_version, UniformCompartment,PlotlyHelper
check_version(LIFE123_VERSION)
OK
Specify the chemicals, the reactions, and the initial concentrations
# Instantiate the simulator and specify the chemicals
# Here we use the "fast" preset for the variable steps, which leads to fewer steps, but generally less-accurate results
uc_fast = UniformCompartment(preset="fast")
# Elementary reaction A + B <-> C
uc_fast.add_reaction(reactants=["A" , "B"], products="C", kF=5., kR=2.)
uc_fast.describe_reactions()
add_reaction(): detected reaction type `ReactionSynthesis` Number of reactions: 1 0: A + B <-> C Elementary Synthesis reaction (kF = 5 / kR = 2 / delta_G = -2,271.4 / K = 2.5 / Temp = 25 C) Chemicals involved in the above reactions: ['A', 'B', 'C']
# Set the initial concentrations of all the chemicals
uc_fast.set_conc({"A": 10., "B": 50., "C": 20.})
uc_fast.single_compartment_react(initial_step=0.004, duration=0.06, variable_steps=True)
23 total variable step(s) taken in 0.046 sec
Number of step re-do's because of elective soft aborts: 3
Norm usage: {'norm_A': 13, 'norm_B': 9, 'norm_C': 9, 'norm_D': 9}
System Time is now: 0.0674
uc_fast.get_history()
| SYSTEM TIME | A | B | C | step | caption | |
|---|---|---|---|---|---|---|
| 0 | 0.000000 | 10.000000 | 50.000000 | 20.000000 | Set concentration | |
| 1 | 0.000864 | 7.874560 | 47.874560 | 22.125440 | 1 | 1st reaction step |
| 2 | 0.001555 | 6.602265 | 46.602265 | 23.397735 | 2 | |
| 3 | 0.002246 | 5.571266 | 45.571266 | 24.428734 | 3 | |
| 4 | 0.002938 | 4.727594 | 44.727594 | 25.272406 | 4 | |
| 5 | 0.003629 | 4.031746 | 44.031746 | 25.968254 | 5 | |
| 6 | 0.004666 | 3.165305 | 43.165305 | 26.834695 | 6 | |
| 7 | 0.005702 | 2.512652 | 42.512652 | 27.487348 | 7 | |
| 8 | 0.006739 | 2.015898 | 42.015898 | 27.984102 | 8 | |
| 9 | 0.007776 | 1.634842 | 41.634842 | 28.365158 | 9 | |
| 10 | 0.008813 | 1.340804 | 41.340804 | 28.659196 | 10 | |
| 11 | 0.009850 | 1.112883 | 41.112883 | 28.887117 | 11 | |
| 12 | 0.010886 | 0.935595 | 40.935595 | 29.064405 | 12 | |
| 13 | 0.011923 | 0.797321 | 40.797321 | 29.202679 | 13 | |
| 14 | 0.013478 | 0.635211 | 40.635211 | 29.364789 | 14 | |
| 15 | 0.015034 | 0.525833 | 40.525833 | 29.474167 | 15 | |
| 16 | 0.016589 | 0.451805 | 40.451805 | 29.548195 | 16 | |
| 17 | 0.018922 | 0.376490 | 40.376490 | 29.623510 | 17 | |
| 18 | 0.021254 | 0.337393 | 40.337393 | 29.662607 | 18 | |
| 19 | 0.024754 | 0.306871 | 40.306871 | 29.693129 | 19 | |
| 20 | 0.030002 | 0.293965 | 40.293965 | 29.706035 | 20 | |
| 21 | 0.037876 | 0.295437 | 40.295437 | 29.704563 | 21 | |
| 22 | 0.049685 | 0.294082 | 40.294082 | 29.705918 | 22 | |
| 23 | 0.067400 | 0.296969 | 40.296969 | 29.703031 | 23 | last reaction step |
uc_fast.plot_history(show_intervals=True)
# Instantiate the simulator and specify the chemicals
uc_slow = UniformCompartment(reactions=uc_fast.get_reactions(), preset="slow")
# Re-use the chemicals and reactions of part 1, but now with the "slow" preset
# Set the initial concentrations of all the chemicals
uc_slow.set_conc({"A": 10., "B": 50., "C": 20.})
uc_slow.single_compartment_react(initial_step=0.004, duration=0.06, variable_steps=True)
80 total variable step(s) taken in 0.166 sec
Number of step re-do's because of elective soft aborts: 2
Norm usage: {'norm_A': 38, 'norm_B': 36, 'norm_C': 36, 'norm_D': 36}
System Time is now: 0.061008
uc_slow.get_history()
| SYSTEM TIME | A | B | C | step | caption | |
|---|---|---|---|---|---|---|
| 0 | 0.000000 | 10.000000 | 50.000000 | 20.000000 | Set concentration | |
| 1 | 0.000160 | 9.606400 | 49.606400 | 20.393600 | 1 | 1st reaction step |
| 2 | 0.000336 | 9.194224 | 49.194224 | 20.805776 | 2 | |
| 3 | 0.000530 | 8.764451 | 48.764451 | 21.235549 | 3 | |
| 4 | 0.000743 | 8.318407 | 48.318407 | 21.681593 | 4 | |
| ... | ... | ... | ... | ... | ... | ... |
| 76 | 0.045329 | 0.294997 | 40.294997 | 29.705003 | 76 | |
| 77 | 0.048708 | 0.294914 | 40.294914 | 29.705086 | 77 | |
| 78 | 0.052424 | 0.294886 | 40.294886 | 29.705114 | 78 | |
| 79 | 0.056511 | 0.294879 | 40.294879 | 29.705121 | 79 | |
| 80 | 0.061008 | 0.294878 | 40.294878 | 29.705122 | 80 | last reaction step |
81 rows × 6 columns
# Instantiate the simulator and specify the chemicals
uc_exact = UniformCompartment(preset="slow", reactions=uc_fast.get_reactions(),
exact=True)
# Re-use the chemicals and reactions of part 1;
# the "slow" preset doesn't particularly matter now because it's just 1 reaction, and we'll be getting the analytical solutin.
# Note the `exact` flag
# Set the initial concentrations of all the chemicals
uc_exact.set_conc({"A": 10., "B": 50., "C": 20.}, snapshot=True)
uc_exact.single_compartment_react(initial_step=0.004, duration=0.06, variable_steps=True)
79 total variable step(s) taken in 0.156 sec
Number of step re-do's because of elective soft aborts: 2
Norm usage: {'norm_A': 38, 'norm_B': 36, 'norm_C': 36, 'norm_D': 36}
System Time is now: 0.061037
uc_exact.get_history()
| SYSTEM TIME | A | B | C | step | caption | |
|---|---|---|---|---|---|---|
| 0 | 0.000000 | 10.000000 | 50.000000 | 20.000000 | Set concentration | |
| 1 | 0.000160 | 9.615719 | 49.615719 | 20.384281 | 1 | 1st reaction step |
| 2 | 0.000336 | 9.213647 | 49.213647 | 20.786353 | 2 | |
| 3 | 0.000530 | 8.794750 | 48.794750 | 21.205250 | 3 | |
| 4 | 0.000743 | 8.360318 | 48.360318 | 21.639682 | 4 | |
| ... | ... | ... | ... | ... | ... | ... |
| 75 | 0.045358 | 0.295598 | 40.295598 | 29.704402 | 75 | |
| 76 | 0.048737 | 0.295238 | 40.295238 | 29.704762 | 76 | |
| 77 | 0.052453 | 0.295046 | 40.295046 | 29.704954 | 77 | |
| 78 | 0.056540 | 0.294950 | 40.294950 | 29.705050 | 78 | |
| 79 | 0.061037 | 0.294906 | 40.294906 | 29.705094 | 79 | last reaction step |
80 rows × 6 columns
C, as a function of time, from the earlier 3 simulations¶p1 = uc_fast.plot_history(chemicals="C", colors=['#F5B914'], title="fast (less precise)", show=False)
p2 = uc_slow.plot_history(chemicals="C", colors=['#CBE504'], title="slow (more precise)", show=False)
p3 = uc_exact.plot_history(chemicals="C", colors=['forestgreen'], title="exact", show=False)
PlotlyHelper.combine_plots([p1, p2, p3], title="Comparison of simulation accuracies", xrange=[0, 0.015])