LAST_REVISED = "May 3, 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 life123 import BioSim1D, ChemData, PlotlyHelper, check_version
check_version(LIFE123_VERSION)
OK
# Initialize the system. We use a RELATIVELY LARGE NUMBER OF BINS,
# to captures the finer changes in the frequency components of the concentration function
chem_data = ChemData(names="A", diffusion_rates=0.5)
bio = BioSim1D(n_bins=500, chem_data=chem_data)
bio.inject_sine_conc(chem_label="A", amplitude=10, bias=30, number_cycles=2)
bio.show_system_snapshot()
SYSTEM SNAPSHOT at time 0:
| A | |
|---|---|
| 0 | 30.000000 |
| 1 | 30.251301 |
| 2 | 30.502443 |
| 3 | 30.753268 |
| 4 | 31.003617 |
| ... | ... |
| 495 | 28.746668 |
| 496 | 28.996383 |
| 497 | 29.246732 |
| 498 | 29.497557 |
| 499 | 29.748699 |
500 rows × 1 columns
# Visualize the system's initial state
bio.visualize_system(title_prefix="Initial System State")
# Show as heatmap
bio.system_heatmaps(title_prefix="Initial System State (as a heatmap)")
# Take a look at the frequency domain of the concentration values
frequency_data = bio.frequency_analysis(chem_label="A")
frequency_data
| Frequency | Relative Amplitude | |
|---|---|---|
| 0 | 0.0 | 3.0 |
| 1 | 2.0 | 1.0 |
ratio = frequency_data.loc[1, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
ratio
0.3333333333333333
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0 | 0.333333 |
bio.diffuse(total_duration=10, n_steps=100)
{'steps': 100}
# Take a look at the frequency domain of the concentration values
frequency_data = bio.frequency_analysis(chem_label="A")
frequency_data
| Frequency | Relative Amplitude | |
|---|---|---|
| 0 | 0.0 | 136826.215286 |
| 1 | 1.0 | 1.000000 |
| 2 | 2.0 | 45466.923974 |
| 3 | 3.0 | 2.992211 |
| 4 | 4.0 | 3.980559 |
| ... | ... | ... |
| 246 | 246.0 | 11.415221 |
| 247 | 247.0 | 11.413727 |
| 248 | 248.0 | 11.412659 |
| 249 | 249.0 | 11.412018 |
| 250 | 250.0 | 11.411805 |
251 rows × 2 columns
ratio = frequency_data.loc[2, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
ratio
0.3322968765783201
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.332297 |
for i in range(49):
bio.diffuse(total_duration=10, n_steps=100)
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[2, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.332297 | |
| 2 | 20.0 | 0.331275 | |
| 3 | 30.0 | 0.330264 | |
| 4 | 40.0 | 0.329262 | |
| 5 | 50.0 | 0.328268 | |
| 6 | 60.0 | 0.327283 | |
| 7 | 70.0 | 0.326304 | |
| 8 | 80.0 | 0.325332 | |
| 9 | 90.0 | 0.324367 | |
| 10 | 100.0 | 0.323409 | |
| 11 | 110.0 | 0.322456 | |
| 12 | 120.0 | 0.321510 | |
| 13 | 130.0 | 0.320569 | |
| 14 | 140.0 | 0.319634 | |
| 15 | 150.0 | 0.318705 | |
| 16 | 160.0 | 0.317781 | |
| 17 | 170.0 | 0.316862 | |
| 18 | 180.0 | 0.315948 | |
| 19 | 190.0 | 0.315040 | |
| 20 | 200.0 | 0.314137 | |
| 21 | 210.0 | 0.313238 | |
| 22 | 220.0 | 0.312345 | |
| 23 | 230.0 | 0.311456 | |
| 24 | 240.0 | 0.310572 | |
| 25 | 250.0 | 0.309692 | |
| 26 | 260.0 | 0.308817 | |
| 27 | 270.0 | 0.307947 | |
| 28 | 280.0 | 0.307081 | |
| 29 | 290.0 | 0.306219 | |
| 30 | 300.0 | 0.305362 | |
| 31 | 310.0 | 0.304509 | |
| 32 | 320.0 | 0.303660 | |
| 33 | 330.0 | 0.302816 | |
| 34 | 340.0 | 0.301976 | |
| 35 | 350.0 | 0.301139 | |
| 36 | 360.0 | 0.300307 | |
| 37 | 370.0 | 0.299479 | |
| 38 | 380.0 | 0.298655 | |
| 39 | 390.0 | 0.297835 | |
| 40 | 400.0 | 0.297018 | |
| 41 | 410.0 | 0.296206 | |
| 42 | 420.0 | 0.295397 | |
| 43 | 430.0 | 0.294592 | |
| 44 | 440.0 | 0.293791 | |
| 45 | 450.0 | 0.292994 | |
| 46 | 460.0 | 0.292200 | |
| 47 | 470.0 | 0.291410 | |
| 48 | 480.0 | 0.290624 | |
| 49 | 490.0 | 0.289841 | |
| 50 | 500.0 | 0.289062 |
bio.visualize_system()
for i in range(150):
bio.diffuse(total_duration=10, n_steps=75) # Notice the gradual decreas of the number of intermediate steps, given the smaller gradient
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[2, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.332297 | |
| 2 | 20.0 | 0.331275 | |
| 3 | 30.0 | 0.330264 | |
| 4 | 40.0 | 0.329262 | |
| ... | ... | ... | ... |
| 196 | 1960.0 | 0.203404 | |
| 197 | 1970.0 | 0.202963 | |
| 198 | 1980.0 | 0.202523 | |
| 199 | 1990.0 | 0.202085 | |
| 200 | 2000.0 | 0.201648 |
201 rows × 3 columns
bio.visualize_system()
for i in range(800):
bio.diffuse(total_duration=10, n_steps=20) # Note how we're gradually increasing the number of intermediate steps, because the gradiants are now smaller
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[2, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.332297 | |
| 2 | 20.0 | 0.331275 | |
| 3 | 30.0 | 0.330264 | |
| 4 | 40.0 | 0.329262 | |
| ... | ... | ... | ... |
| 996 | 9960.0 | 0.062422 | |
| 997 | 9970.0 | 0.062358 | |
| 998 | 9980.0 | 0.062295 | |
| 999 | 9990.0 | 0.062232 | |
| 1000 | 10000.0 | 0.062168 |
1001 rows × 3 columns
bio.visualize_system()
PlotlyHelper.plot_pandas(df=bio.get_history(), x_var="SYSTEM TIME", fields="ratio",
y_label="ratio",
title= "Component of frequency=2, relative to amplitude of constant bias",
colors="orange")
# Same, but wigh log scale for y-axis (and save the figure object in a variable)
fig_freq_2 = PlotlyHelper.plot_pandas(df=bio.get_history(), x_var="SYSTEM TIME", fields="ratio",
log_y=True, y_label="ratio",
title= "Component of frequency=2, relative to amplitude of constant bias<br>(log scale in y-axis)",
colors="orange")
fig_freq_2.show()
bio = BioSim1D(n_bins=500, chem_data=chem_data)
bio.inject_sine_conc(chem_label="A", amplitude=10, bias=30, number_cycles=10) # x5 higher frequency than before
bio.visualize_system(title_prefix="Initial System State")
# Show as heatmap
bio.system_heatmaps(title_prefix="Initial System State (as a heatmap)")
# Take a look at the frequency domain of the concentration values
frequency_data = bio.frequency_analysis(chem_label="A")
frequency_data
| Frequency | Relative Amplitude | |
|---|---|---|
| 0 | 0.0 | 3.0 |
| 1 | 10.0 | 1.0 |
ratio = frequency_data.loc[1, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
ratio
0.3333333333333333
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0 | 0.333333 |
bio.diffuse(total_duration=10, n_steps=100)
{'steps': 100}
# Take a look at the frequency domain of the concentration values
frequency_data = bio.frequency_analysis(chem_label="A")
frequency_data.loc[10]
Frequency 10.000000 Relative Amplitude 8721.103713 Name: 10, dtype: float64
ratio = frequency_data.loc[10, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
ratio
0.308390736321019
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.308391 |
bio.visualize_system()
for i in range(4):
bio.diffuse(total_duration=10, n_steps=100)
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[10, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.visualize_system()
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.308391 | |
| 2 | 20.0 | 0.285576 | |
| 3 | 30.0 | 0.264622 | |
| 4 | 40.0 | 0.245345 | |
| 5 | 50.0 | 0.227592 |
for i in range(10):
bio.diffuse(total_duration=10, n_steps=100)
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[10, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.visualize_system()
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.308391 | |
| 2 | 20.0 | 0.285576 | |
| 3 | 30.0 | 0.264622 | |
| 4 | 40.0 | 0.245345 | |
| 5 | 50.0 | 0.227592 | |
| 6 | 60.0 | 0.211230 | |
| 7 | 70.0 | 0.196140 | |
| 8 | 80.0 | 0.182216 | |
| 9 | 90.0 | 0.169363 | |
| 10 | 100.0 | 0.157493 | |
| 11 | 110.0 | 0.146526 | |
| 12 | 120.0 | 0.136390 | |
| 13 | 130.0 | 0.127020 | |
| 14 | 140.0 | 0.118354 | |
| 15 | 150.0 | 0.110337 |
for i in range(35):
bio.diffuse(total_duration=10, n_steps=100)
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[10, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.visualize_system()
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.308391 | |
| 2 | 20.0 | 0.285576 | |
| 3 | 30.0 | 0.264622 | |
| 4 | 40.0 | 0.245345 | |
| 5 | 50.0 | 0.227592 | |
| 6 | 60.0 | 0.211230 | |
| 7 | 70.0 | 0.196140 | |
| 8 | 80.0 | 0.182216 | |
| 9 | 90.0 | 0.169363 | |
| 10 | 100.0 | 0.157493 | |
| 11 | 110.0 | 0.146526 | |
| 12 | 120.0 | 0.136390 | |
| 13 | 130.0 | 0.127020 | |
| 14 | 140.0 | 0.118354 | |
| 15 | 150.0 | 0.110337 | |
| 16 | 160.0 | 0.102919 | |
| 17 | 170.0 | 0.096052 | |
| 18 | 180.0 | 0.089695 | |
| 19 | 190.0 | 0.083806 | |
| 20 | 200.0 | 0.078351 | |
| 21 | 210.0 | 0.073296 | |
| 22 | 220.0 | 0.068611 | |
| 23 | 230.0 | 0.064267 | |
| 24 | 240.0 | 0.060238 | |
| 25 | 250.0 | 0.056500 | |
| 26 | 260.0 | 0.053032 | |
| 27 | 270.0 | 0.049813 | |
| 28 | 280.0 | 0.046824 | |
| 29 | 290.0 | 0.044048 | |
| 30 | 300.0 | 0.041469 | |
| 31 | 310.0 | 0.039073 | |
| 32 | 320.0 | 0.036846 | |
| 33 | 330.0 | 0.034775 | |
| 34 | 340.0 | 0.032849 | |
| 35 | 350.0 | 0.031057 | |
| 36 | 360.0 | 0.029389 | |
| 37 | 370.0 | 0.027836 | |
| 38 | 380.0 | 0.026390 | |
| 39 | 390.0 | 0.025043 | |
| 40 | 400.0 | 0.023788 | |
| 41 | 410.0 | 0.022618 | |
| 42 | 420.0 | 0.021526 | |
| 43 | 430.0 | 0.020508 | |
| 44 | 440.0 | 0.019558 | |
| 45 | 450.0 | 0.018671 | |
| 46 | 460.0 | 0.017842 | |
| 47 | 470.0 | 0.017068 | |
| 48 | 480.0 | 0.016345 | |
| 49 | 490.0 | 0.015668 | |
| 50 | 500.0 | 0.015035 |
for i in range(50):
bio.diffuse(total_duration=10, n_steps=100)
frequency_data = bio.frequency_analysis(chem_label="A")
ratio = frequency_data.loc[10, "Relative Amplitude"] / frequency_data.loc[0, "Relative Amplitude"]
bio.add_snapshot(data_snapshot={"ratio": ratio})
bio.visualize_system()
Most of the concentration graph is now flat as a board!
bio.get_history()
| SYSTEM TIME | ratio | caption | |
|---|---|---|---|
| 0 | 0.0 | 0.333333 | |
| 1 | 10.0 | 0.308391 | |
| 2 | 20.0 | 0.285576 | |
| 3 | 30.0 | 0.264622 | |
| 4 | 40.0 | 0.245345 | |
| ... | ... | ... | ... |
| 96 | 960.0 | 0.005431 | |
| 97 | 970.0 | 0.005376 | |
| 98 | 980.0 | 0.005324 | |
| 99 | 990.0 | 0.005273 | |
| 100 | 1000.0 | 0.005224 |
101 rows × 3 columns
PlotlyHelper.plot_pandas(df=bio.get_history(), x_var="SYSTEM TIME", fields="ratio",
y_label="ratio",
title= "Component of frequency=10, relative to amplitude of constant bias",
colors="red")
# Same, but wigh log scale for y-axis (and save the figure object in a variable)
fig_freq_10 = PlotlyHelper.plot_pandas(df=bio.get_history(), x_var="SYSTEM TIME", fields="ratio",
log_y=True, y_label="ratio",
title= "Component of frequency=10, relative to amplitude of constant bias<br>(log scale in y-axis)",
colors="red")
fig_freq_10.show()
fig_freq_2
# Combine the last 2 plots
PlotlyHelper.combine_plots(fig_list=[fig_freq_2, fig_freq_10],
title="Superposed plots for frequency 2 and 10",
curve_labels=["Component of frequency=2", "Component of frequency=10"])