#!/usr/bin/env python # coding: utf-8 # # "Crossing the border in disguise" : a chemical crosses a membrane impermeable to it, # #### by first undergoing a reaction converting it into a different chemical, to which the membrane is permeable, # #### and then re-constituting the first chemical outside of the membrane, thru the reverse reaction. # #### Reaction-diffusion `A <-> B` in 1D, in the presence of membranes with selective permeability to passive transport. # # Eventually, the reaction, the passive membrane transport and the diffusion all come to an equilibrium. # ### TAGS : "reactions 1D", "diffusion 1D", "membranes 1D" # In[1]: LAST_REVISED = "June 6, 2025" LIFE123_VERSION = "1.0.0rc6" # Library version this experiment is based on # In[2]: #import set_path # Using MyBinder? Uncomment this before running the next cell! # In[3]: #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 check_version, BioSim1D, ChemData, UniformCompartment # In[4]: check_version(LIFE123_VERSION) # In[ ]: # ## Prepare the initial system, for starters with IM-PERMEABLE membranes # with two chemicals `A` and `B` # In[5]: chem_data = ChemData(diffusion_rates=[2., 2.], plot_colors=["turquoise", "green"]) # Names "A", "B" automatically assigned bio = BioSim1D(n_bins=9, chem_data=chem_data) # In[6]: reactions = bio.get_reactions() # Reaction A <-> B , 1st-order kinetics, mostly (but not hugely) in the forward direction reactions.add_reaction(reactants="A", products="B", forward_rate=8., reverse_rate=2.) reactions.describe_reactions() # In[7]: bio.set_bin_conc(bin_address=4, chem_label="A", conc=10.) # Set the initial concentration of `A` in middle bin bio.membranes().set_membranes(membranes=[ (4,5) ]) # By default impermeable bio.describe_state() # In[8]: bio.system_heatmaps() # In[ ]: # ## Request history-keeping for some bins # In[9]: # Request to save the concentration history at the bin with the initial concentration injection, # and at a couple of other bins bio.enable_history(bins=[0, 2, 4], frequency=10, take_snapshot=True) # In[ ]: # In[ ]: # ### Advance reaction to equilibrium # The membranes are impermeable for now; so, no transport across them occurs # In[10]: delta_t = 0.002 # This will be our time "quantum" (fixed time step for reactions, passive transport and diffusion) for this experiment # In[11]: bio.react_diffuse(time_step=delta_t, n_steps=350) bio.describe_state() # In[12]: bio.system_heatmaps() # In[13]: bio.plot_history_single_bin(bin_address=4) # In[14]: # Check the reaction equilibrium bio.reaction_in_equilibrium(bin_address=4, rxn_index=0, explain=True) # # In[ ]: # # Let's siphon off the product `B` from the central bin 4, by making the membrane permeable to it # while still remaining impermeable to `A`. Note the system time when this happens: # In[15]: bio.get_system_time() # In[16]: bio.membranes().change_permeability("B", 1.) # Make the membrane permeable to `B` (and only to `B`!) # In[ ]: # ### Advance the reaction - and now also the passive transport of `B` across the membrane, and its diffusion outside # In[17]: bio.react_diffuse(time_step=delta_t, n_steps=30) bio.describe_state() # In[18]: bio.system_heatmaps() # Notice what's happening: # 1. `B` is diffusing away (because we made the membranes permeable to it) # 2. By Le Chatelier's principle, the reaction `A <-> B` in bin 4 is moving forward, because we're siphoning off the product `B` # 3. In the other bins, `A` is re-forming from `B`, from the reverse reaction # In[ ]: # ### Continue advancing the reaction, passive transport of `B`, and diffusion # In[19]: bio.react_diffuse(time_step=delta_t, n_steps=50) bio.describe_state() # In[20]: bio.system_heatmaps() # Notice how the concentration of `A` in the central bin 4 is continuing to drop # In[21]: bio.plot_history_single_bin(bin_address=4, vertical_lines_to_add=[0.7], title_prefix="Dashed vertical line at time when the membranes were made permeable to `B`") # In[ ]: # In[22]: bio.react_diffuse(time_step=delta_t, n_steps=150) bio.describe_state() # In[23]: bio.system_heatmaps() # Notice how [A] in bin 4 is continuing to drop, as `A` keeps turns into `B` # In[ ]: # In[24]: bio.react_diffuse(time_step=delta_t, n_steps=500) bio.describe_state() # In[25]: bio.system_heatmaps() # In[ ]: # In[26]: bio.react_diffuse(time_step=delta_t, n_steps=1500) bio.describe_state() # In[27]: bio.system_heatmaps() # In[ ]: # ### Let's take the system to equilibrium, in reactions and diffusion # In[28]: bio.react_diffuse(time_step=delta_t, n_steps=3000) bio.describe_state() # In[29]: bio.system_heatmaps() # In[30]: # Check the reaction equilibrium in one of the bins (doesn't matter which one, since all bin concentrations are now the same) bio.reaction_in_equilibrium(bin_address=0, rxn_index=0, explain=True) # ### From a casual glance at the past heatmaps, it might seem that `A` has diffused to equilibrium across all bins... # ### But the actual mechanism was that `A` (trapped in bin 4 by a membrane impermeable to it) has transformed into `B`, which in turn has passively crossed the membrane, and then diffused across all bins, while at the same time forming `A` by the reverse reaction in all bins outside the membrane. # #### All said and done, `A` has "found a way, thru its disguise as `B`" to indirectly pass thru an impermeable membrane! # In[31]: # Let's look at the central bin 4 bio.plot_history_single_bin(bin_address=4, vertical_lines_to_add=[0.7], title_prefix="Dashed vertical line at time when the membranes were made permeable to `B`;" \ "
notice the syphoning off of `B` and the resumed advance of the reaction that consumes `A`.") # In[32]: # Let's look at a bin CLOSE to the central bin 4 bio.plot_history_single_bin(bin_address=2, vertical_lines_to_add=[0.7], title_prefix="Dashed vertical line at time when the membranes were made permeable to `B`;" \ "
notice the QUICK arrival of `B` by diffusion, and the subsequent formation of `A` by reverse reaction.") # In[33]: # Let's look at a bin FAR from the central bin 4 bio.plot_history_single_bin(bin_address=0, vertical_lines_to_add=[0.7], title_prefix="Dashed vertical line at time when the membranes were made permeable to `B`;" \ "
notice the SLOW arrival of `B` by diffusion, and the subsequent formation of `A` by reverse reaction.") # In[ ]: