Event manager

Event manager#

The event manager is the system which manage the different behavior of a simulation. It is composed of two lists :

  • current : list of actions to be executed during the current simulation step.

  • next : list of actions to be executed for the next simulation step, this list is filled during the current simulation step.

A behavior is a function which describes/contains the actions requested to realize an event. For example, the behavior which describe the cell division is composed of :

  • growing cell area until its reach a certain threshold

  • dividing cell into two daughter cell

Event manager principle

# Generate 2D tyssue

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

import ipywidgets as widgets
from IPython import display
import ipyvolume as ipv

# Core object
from tyssue import Sheet
# Simple 2D geometry
from tyssue import PlanarGeometry as sgeom
# Visualisation
from tyssue.draw import (
    sheet_view,
    highlight_faces,
    create_gif,
    browse_history
)

sheet = Sheet.planar_sheet_2d(
    'basic2D', # a name or identifier for this sheet
    nx=6, # approximate number of cells on the x axis
    ny=7, # approximate number of cells along the y axis
    distx=1, # distance between 2 cells along x
    disty=1, # distance between 2 cells along y
    noise=0 # some position noise
)
sgeom.update_all(sheet)

# Give the tissue a nice hear cut ;)
sheet.sanitize(trim_borders=True, order_edges=True)
sgeom.update_all(sheet)
/tmp/ipykernel_3629/1962977038.py:6: DeprecationWarning: 
Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),
(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)
but was not found to be installed on your system.
If this would cause problems for you,
please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466
        
  import pandas as pd
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 10
      8 import ipywidgets as widgets
      9 from IPython import display
---> 10 import ipyvolume as ipv
     12 # Core object
     13 from tyssue import Sheet

File ~/checkouts/readthedocs.org/user_builds/tyssue/conda/latest/lib/python3.12/site-packages/ipyvolume/__init__.py:8
      6 from ipyvolume import datasets  # noqa: F401
      7 from ipyvolume import embed  # noqa: F401
----> 8 from ipyvolume.widgets import *  # noqa: F401, F403
      9 from ipyvolume.transferfunction import *  # noqa: F401, F403
     10 from ipyvolume.pylab import *  # noqa: F401, F403

File ~/checkouts/readthedocs.org/user_builds/tyssue/conda/latest/lib/python3.12/site-packages/ipyvolume/widgets.py:23
     21 import ipyvolume._version
     22 from ipyvolume.traittypes import Image
---> 23 from ipyvolume.serialize import (
     24     array_cube_tile_serialization,
     25     array_serialization,
     26     array_sequence_serialization,
     27     color_serialization,
     28     texture_serialization,
     29 )
     30 from ipyvolume.transferfunction import TransferFunction
     31 from ipyvolume.utils import debounced, grid_slice, reduce_size

File ~/checkouts/readthedocs.org/user_builds/tyssue/conda/latest/lib/python3.12/site-packages/ipyvolume/serialize.py:17
     15 import ipywidgets
     16 import ipywebrtc
---> 17 from ipython_genutils.py3compat import string_types
     19 from ipyvolume import utils
     22 logger = logging.getLogger("ipyvolume")

ModuleNotFoundError: No module named 'ipython_genutils'
# Visualisation of the tissue
fig, ax = sheet_view(sheet, mode="2D")
fig.set_size_inches(8, 8)
../_images/77a30af91608139dd93a06a110c3e4abfa10cddfa5ba379d98a0ecb9bce07175.png
from tyssue.dynamics.planar_vertex_model import PlanarModel as smodel
from tyssue.solvers import QSSolver
from pprint import pprint

specs = {
    'edge': {
        'is_active': 1,
        'line_tension': 0.12,
        'ux': 0.0,
        'uy': 0.0,
        'uz': 0.0
    },
   'face': {
       'area_elasticity': 1.0,
       'contractility': 0.04,
       'is_alive': 1,
       'prefered_area': 1.0},
   'settings': {
       'grad_norm_factor': 1.0,
       'nrj_norm_factor': 1.0
   },
   'vert': {
       'is_active': 1
   }
}


# Update the specs (adds / changes the values in the dataframes' columns)
sheet.update_specs(specs)
# Check the tissue is at its equilibrium
solver = QSSolver()
res = solver.find_energy_min(sheet, sgeom, smodel)
# Visualisation of the tissue
fig, ax = sheet_view(sheet, mode="2D")
../_images/dfa7c90195ec3506994236ce5d306852678eed4fb6c85a068b28d4361b69fe2d.png

Write a behavior function#

Behavior parameters function are composed of two parts :

  • signature part, which contains sheet and manager parameter

  • keywords part, which is specific to one behavior function

To add a behavior to the manager, append method has to be used, and it need as parameter the function name and the keyword part.

from tyssue.topology.sheet_topology import cell_division

def division(sheet, manager, cell_id=0, crit_area=2.0, growth_rate=0.1, dt=1.):
    """Defines a division behavior.
    
    Parameters
    ----------
    
    sheet: a :class:`Sheet` object
    cell_id: int
        the index of the dividing cell
    crit_area: float
        the area at which 
    growth_rate: float
        increase in the prefered are per unit time
        A_0(t + dt) = A0(t) * (1 + growth_rate * dt)
    """

    
    if sheet.face_df.loc[cell_id, "area"] > crit_area:
        # restore prefered_area
        sheet.face_df.loc[12, "prefered_area"] = 1.0
        # Do division
        daughter = cell_division(sheet, cell_id, sgeom)
        # Update the topology
        sheet.reset_index(order=True)
        # update geometry
        sgeom.update_all(sheet)
        print(f"cell n°{daughter} is born")
    else:
        # 
        sheet.face_df.loc[12, "prefered_area"] *= (1 + dt * growth_rate)
        manager.append(division, cell_id=cell_id)

When the manager is initialised, wait function is aded by default in the current event list. Any new event added to the manager are added to the next list.

from tyssue.behaviors import EventManager

# Initialisation of manager 
manager = EventManager("face")

# Add action/event to the manager
manager.append(division, cell_id=12)
print('manager.current :')
print(manager.current)
print()
print('manager.next :')
print(manager.next)
manager.current :
deque([(<function wait at 0x7eff4f6440d0>, {'face_id': -1, 'n_steps': 1})])

manager.next :
deque([(<function division at 0x7eff4d96f490>, {'cell_id': 12})])
from tyssue import History

t = 0
stop = 30

# The History object records all the time steps 
history = History(sheet)

while manager.current and t < stop:
    # Execute the event in the current list
    manager.execute(sheet)
    t += 1
    sheet.reset_index(order=True)
    # Find energy min
    res = solver.find_energy_min(sheet, sgeom, smodel)
    history.record()
    # Switch event list from the next list to the current list
    manager.update()
cell n°25 is born
draw_specs = {
    "edge": {
        "color": lambda sheet: sheet.edge_df.length
    },
    "face": {
        "visible": True,
        "color": lambda sheet: sheet.face_df.area,
        "color_range": (0, 2)
    }
}

create_gif(history, "growth.gif", num_frames=30, margin=5, **draw_specs)
display.Image("growth.gif")
../_images/bdae8b4e175b03a61a548e2c179c6b0fe99975ab5b1aaaec5375822a870838d5.gif
# Visualisation of the tissue
fig, ax = sheet_view(sheet, mode="2D")
fig.set_size_inches(8, 8)
../_images/4d6c1b881bac53802fb7fb8aea1e96916cf781d1a26c9b4d15d1160d3f16bd4b.png