- Mitosis steppable is described in great detail in “Python Scripting Manual” - see for example
but because of its importance we are including a copy of that description here.
In developmental simulations we often need to simulate cells which grow
and divide. In earlier versions of CompuCell3D we had to write quite
complicated plugin to do that which was quite cumbersome and
unintuitive. The only advantage of the plugin was that mitosis was
taking place immediately after the pixel copy which had triggered
mitosis condition. This guaranteed that any cell which was supposed
divide at any instance in the simulation, actually did. However, because
state of the simulation is normally observed after completion of full a
Monte Carlo Step, and not in the middle of MCS it makes actually more
sense to implement
Mitosis as a steppable. Let us examine the simplest
simulation which involves mitosis. We start with a single cell and grow
it. When cell reaches critical (doubling) volume it divides. We check if
the cell has reached doubling volume at the end of each MCS. The folder
containing this simulation is
Demos/CompuCellPythonTutorial/steppableBasedMitosis. The mitosis algorithm is implemented in Demos/CompuCellPythonTutorial/steppableBasedMitosis/Simulation/steppableBasedMitosisSteppables.py
from PySteppables import * from PySteppablesExamples import MitosisSteppableBase import CompuCell class VolumeParamSteppable(SteppableBasePy): def __init__(self, _simulator, _frequency=1): SteppableBasePy.__init__(self, _simulator, _frequency) def start(self): for cell in self.cellList: cell.targetVolume = 25 cell.lambdaVolume = 2.0 def step(self, mcs): for cell in self.cellList: cell.targetVolume += 1 class MitosisSteppable(MitosisSteppableBase): def __init__(self, _simulator, _frequency=1): MitosisSteppableBase.__init__(self, _simulator, _frequency) # 0 - parent child position will be randomized between mitosis event # negative integer - parent appears on the 'left' of the child # positive integer - parent appears on the 'right' of the child self.setParentChildPositionFlag(-1) def step(self, mcs): cells_to_divide =  for cell in self.cellList: if cell.volume > 50: cells_to_divide.append(cell) for cell in cells_to_divide: # to change mitosis mode leave one of the below lines uncommented self.divideCellRandomOrientation(cell) def updateAttributes(self): self.parentCell.targetVolume /= 2.0 # reducing parent target volume self.cloneParent2Child() if self.parentCell.type == self.CONDENSING: self.childCell.type = self.NONCONDENSING else: self.childCell.type = self.CONDENSING
Two steppables:`` VolumeParamSteppable`` and
MitosisSteppable are the
essence of the above simulation. The first steppable initializes volume
constraint for all the cells present at
T=0 MCS (only one cell) and then
10 MCS (see the frequency with which
initialized to run -
it increases target volume of cells, effectively causing cells to grow.
from steppableBasedMitosisSteppables import VolumeParamSteppable volumeParamSteppable=VolumeParamSteppable(sim ,10) steppableRegistry.registerSteppable(volumeParamSteppable) from steppableBasedMitosisSteppables import MitosisSteppable mitosisSteppable=MitosisSteppable(sim, 10) steppableRegistry.registerSteppable(mitosisSteppable)
The second steppable checks every
10 MCS (we can, of course, run it
every MCS) if cell has reached doubling volume of
50. If it did such
cell is added to the list cells_to_divide. After construction of
cells_to_divide is complete we iterate over this list and divide all
the cells in it.
It is important to divide cells outside the loop where we iterate over entire cell inventory. If we keep dividing cells in this loop we are adding elements to the list over which we iterate over and this might have unwanted side effects. The solution is to use use list of cells to divide as we did in the example.
Notice that we call
self.divideCellRandomOrientation(cell) function to
divide cells. Other modes of division are available as well and they are
self.divideCellOrientationVectorBased(cell,1,0,0) self.divideCellAlongMajorAxis(cell) self.divideCellAlongMinorAxis(cell)
MitosisSteppableBase class (defined in
PySteppablesExamples.py).It is the base class which ensures that
after we call any of the cell dividing function (e.g.
divideCellRandomOrientation) CompuCell3D will automatically call
updateAttributes function as well.
updateAttributes function is very
important and we must call it in order to ensure integrity and sanity of
the simulation. During mitosis a new cell is created (accessed in Python
as childCell – defined in
self.mitosisSteppable.childCell) and as such this cell is uninitialized.
It does have default attributes (read-only) of a cell such as volume,
surface (if we decide to use surface constraint or
plugin) but all other parameters of such cell are set to default values.
In our simulation we have been setting
individually for each cell. After mitosis
childCell will need those
parameters to be set as well. To make things more interesting, in our
simulation we decided to change type of cell to be different than type
of parent cell. In more complex simulations where cells have more
attributes which are used in the simulation, we have to make sure that
childCell and its attributes get
properly initialized. It is also very common practice to change
attributes of parentCell after mitosis as well to account for the fact
that parentCell is not the original parentCell from before the mitosis.
If you specify orientation vector for the mitosis the actual division will take place along the line/plane perpendicular to this vector.
The name of the function where we update attributes after
mitosis has to be exactly
updateAtttributes. If it is called differently
CC3D will not call it automatically. We can of course call such function
by hand, immediately we do the mitosis but this is not very elegant