In the crypt tutorial, we used an existing cell killer class to define
how cells were sloughed off the top of a crypt. In this tutorial we show
how to create a new cell killer class, and how this can be used in a cell-based
simulation.
As in previous cell-based Chaste tutorials, we begin by including the necessary
header file and archiving headers.
The next header defines a base class for cell killers, from which the new
cell killer class will inherit.
The next header defines a writer which outputs information on cells killed to the file
removals.dat .
The remaining header files define classes that will be used in the cell-based
simulation test. We have encountered each of these header files in previous cell-based
Chaste tutorials.
As an example, let us consider a cell killer that labels any cells in a
two-dimensional cell population which lie outside the elliptical domain given in
Cartesian coordinates by the equation $\left(\frac{x}{20}\right)^2 + \left(\frac{y}{10}\right)^2 < 1$.
To implement this we define a new cell killer class, MyCellKiller,
which inherits from AbstractCellKiller and overrides the
CheckAndLabelCellsForApoptosisOrDeath() method.
Note that usually this code would be separated out into a separate declaration in
a .hpp file and definition in a .cpp file.
The first public method is a default constructor, which just calls the base
constructor.
The second public method overrides CheckAndLabelCellsForApoptosisOrDeath().
This method iterates over all cells in the population, and calls KillCell() on
any cell whose centre is located outside the ellipse $(\frac{x}{20})^2 + (\frac{y}{10})^2 < 1$.
This line marks the cell as killed and stores removal information for use by
by the cell writers if the writer CellRemovalLocationsWriter is included.
The final public method overrides OutputCellKillerParameters().
This method outputs any member variables to a specified results file rParamsFile.
In our case, there are no parameters, so we simply call the method on the base class.
Nonetheless, we still need to override the method, since it is pure virtual in the base
class.
As mentioned in Creating And Using A New Cell Cycle Model, we need to include the next block
of code to be able to archive the cell killer object in a cell-based
simulation, and to obtain a unique identifier for our new cell killer for writing
results to file.
We only need to include the next block of code if we wish to be able to archive (save or load)
the cell killer object in a cell-based simulation. We must define save_construct_data and
load_construct_data methods, which archive the cell killer constructor input argument(s)
(in this case, a CellPopulation).
This completes the code for MyCellKiller. Note that usually this code
would be separated out into a separate declaration in a .hpp file and definition
in a .cpp file.
We begin by testing that our new cell-cycle model is implemented correctly.
We use the honeycomb mesh generator to create a honeycomb mesh.
We then construct and initialise some cells, each with a
FixedG1GenerationalCellCycleModel, using the helper class
CellsGenerator.
Now that we have defined the mesh and cells, we can define the cell population. The
constructor takes in the mesh and the cells vector.
We now use the cell population to construct a cell killer object.
To store information about the lovations and times of the killed cells use the
CellRemovalLocationsWriter
To test that we have implemented the cell killer correctly, we call the
overridden method CheckAndLabelCellsForApoptosisOrDeath…
… and check that any cell whose centre is located outside the ellipse
$(\frac{x}{20})^2 + (\frac{y}{10})^2 < 1$ has indeed been labelled as dead.
As an extra test, we now remove any dead cells and check that all
remaining cells are indeed located within the ellipse.
The last chunk of code provides an archiving test for the cell killer.
We create an output archive, save the existing cell killer object via
a pointer, then create an input archive and load the cell killer. If
the cell killer had any member variables, then we would test that these
were correctly initialised when the cell killer is loaded.
We now provide a test demonstrating how MyCellKiller can be used
in a cell-based simulation.
We proceed as before, creating a mesh-based cell population.
We now use the cell population to construct a cell killer object. This object
must be added to the cell-based simulation as a boost::shared_ptr, so we make
use of the macro MAKE_PTR_ARG (defined in the header SmartPointers.hpp).
We then pass in the cell population into an OffLatticeSimulation,
and set the output directory and end time.
We create a force law and pass it to the OffLatticeSimulation.
We now pass the cell killer into the cell-based simulation.