Mitosis Steppable.¶
- Mitosis steppable is described in great detail in “Python Scripting Manual” - see for example
- https://pythonscriptingmanual.readthedocs.io/en/latest/mitosis.html?highlight=mitosis
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
File:
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
every 10
MCS (see the frequency with which VolumeParamSteppable
in
initialized to run -
Demos/CompuCellPythonTutorial/steppableBasedMitosis/Simulation/steppableBasedMitosis.py)
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.
Warning
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
as follows:
self.divideCellOrientationVectorBased(cell,1,0,0)
self.divideCellAlongMajorAxis(cell)
self.divideCellAlongMinorAxis(cell)
Notice that MitosisSteppable
inherits 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 MitosisSteppableBase
-
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 SurfaceTracker
plugin) but all other parameters of such cell are set to default values.
In our simulation we have been setting targetVolume
and lambdaVolume
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
in the updateAttributes
function 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.
Note
If you specify orientation vector for the mitosis the actual division will take place along the line/plane perpendicular to this vector.
Note
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
solution.