Source code for cellsystem.cellsystem

"""
The cell simulation with logging.

"""

from .simulation import System, CellLine, World, behavior
from   .logging  import logged, FullLog
import random as rnd



[docs]class SimpleCells(CellLine): """A cell line representing simple cells with default behaviors. A cell from this line performs: - Cell division, - Cell death, - Cell migration, - Cell genome mutation. """ def __init__(self, *args, genome_alphabet=None, **kwargs): # Initialize as usual. super().__init__(*args, **kwargs) # Register the default actions self.add_behaviors(*self._init_behaviors()) # --- def _init_behaviors(self): """Initialize the behaviors for cells in this lineage.""" behaviors = [ # --- Cell mutation behavior('mutation', actionfn=self.mutation, probability=self.mutation_probability), # --- Cell migration behavior('migration', actionfn=self.migration, probability=self.migration_probability), # --- Cell division behavior('division', actionfn=self.division, probability=self.division_probability), # --- Cell death behavior('death', actionfn=self.death, probability=self.death_probability), ] # The relative weights of each action. # If an action has a bigger weigth than # the others, it has a correspondingly # bigger probability to be chosen weights = [1] * len(behaviors) return behaviors, weights # ---
[docs] @logged('newcell', prepare=False) def add_cell_to(self, site): """Add a new, initialized cell to the given site. Return the added cell to the caller. """ new = self.new_cell() new.add_to(site) # Return the new cell return new
# ---
[docs] @staticmethod def migration_probability(cell): """Migration probability for this cell.""" return 1
# ---
[docs] @staticmethod def migration(cell): """Migrate to a neighboring cell.""" # Get the destination site next_site = cell.site.random_neighbor() # Migrate to the new site cell.site.remove_guest(cell) next_site.add_guest(cell) cell.site = next_site return cell
# ---
[docs] @staticmethod def mutation_probability(cell): """Probability to mutate if selected for it.""" return 1
# ---
[docs] @staticmethod def mutation(cell): """Do a single site mutation.""" # Get the genome characteristics # Convert alphabet to tuple to call rnd.choice with it alphabet = tuple(cell.genome_alphabet) genome_length = len(cell.genome) # Assemble the mutation position = rnd.randrange(genome_length) # Pick a random position in the genome mutated = rnd.choice(alphabet) # Mutate cell.add_mutation(position, mutated) return cell
# ---
[docs] @staticmethod def death_probability(cell): """Cellular death probability.""" # Avoid killing all cells. if cell.lineage.total_cells > 1: return 0.6 else: return 0
# ---
[docs] @staticmethod def death(cell): """Cellular death.""" cell.site.remove_guest(cell) cell.lineage.handle_death(cell) return cell
# --- @staticmethod def _init_daughter(cell): "Add a new daughter of the cell in an appropriate site." # Create the daughter cell daughter = cell.new_daughter() # Place the daughter site = cell.site daughter.add_to(site.random_neighbor()) return daughter # ---
[docs] @staticmethod def division_probability(cell): """Probability that this cell will divide if selected for division.""" return 1
# ---
[docs] @staticmethod def division(cell, preserve_father=False): """Cell division. Get a new daughter of this cell and place it in a nearby neighboring site. """ # Create the daughter cell and add it to a site daughter = SimpleCells._init_daughter(cell) # If the preserveFather flag is set, we want a # father cell and a daughter cell after the division (like # the gemation process on yeasts), else, we want both # resulting cells to be daughters of the father cell. if not preserve_father: # New daughter placed on an appropriate site other_daughter = SimpleCells._init_daughter(cell) # Remove previous cell SimpleCells.death(cell) return daughter, other_daughter
# --- # --- SimpleCells
[docs]class CellSystem(System): """A system simulating cell growth. A cell system is a system subclass, with the automatic initialization of three main entities: 1. Cells represented by a cell line. 2. A 'world' representing the space that the cells inhabit, and; 3. A 'log' that follows and makes a record of the cells' actions. Each part can be accessed by ``system['cells']``, ``system['world']`` and ``system['log']`` respectively. """ def __init__(self, *args, grid_shape=(100, 100), init_genome=None, **kwargs): """Initialization process.""" super().__init__(*args, **kwargs) # Initialize world self.add_entity( World(shape=grid_shape), name='world', procesable=False) # Initialize log self.add_entity( FullLog(), name='log', procesable=False) # Initialize the cells self.add_entity( SimpleCells(genome=init_genome), name='cells') self['cells'].register_log(self['log']) # ---
[docs] def seed(self): 'Place a single cell in the middle of the world.' # Fetch the middle of the grid world = self['world'] # Add cell self['cells'].add_cell_to( world.middle, log=self['log'])
# --- # --- CellSystem