UserTutorials/RunningDeltaNotchSimulations

This tutorial is automatically generated from the file trunk/cell_based/test/tutorial/TestRunningDeltaNotchSimulationsTutorial.hpp at revision r21413. Note that the code is given in full at the bottom of the page.

An example showing how to run Delta/Notch simulations

Introduction

In this tutorial we show how Chaste can be used to simulate a growing cell monolayer culture into which a simple model of Delta/Notch signalling is incorporated. This model was developed by Collier et al. ("Pattern formation by lateral inhibition with feedback: a mathematical model of delta-notch intercellular signalling", J. Theor. Biol. 183:429-446) and comprises two ODEs to describe the evolution in concentrations of Delta and Notch in each cell. The ODE for Notch includes a reaction term that depends on the mean Delta concentration among neighbouring cells. Thus in this simulation each cell needs to be able to access information about its neighbours. We use the CellData class to facilitate this, and introduce a subclass of OffLatticeSimulation called DeltaNotchOffLatticeSimulation to handle the updating of CellData at each time step as cell neighbours change.

The test

As in previous tutorials, we begin by including the necessary header files. We have encountered these files already. Recall that often, either CheckpointArchiveTypes.hpp or CellBasedSimulationArchiver.hpp must be included the first Chaste header.

#include <cxxtest/TestSuite.h>
#include "CheckpointArchiveTypes.hpp"
#include "AbstractCellBasedTestSuite.hpp"
#include "HoneycombMeshGenerator.hpp"
#include "HoneycombVertexMeshGenerator.hpp"
#include "NodeBasedCellPopulation.hpp"
#include "OffLatticeSimulation.hpp"
#include "VertexBasedCellPopulation.hpp"
#include "NagaiHondaForce.hpp"
#include "SimpleTargetAreaModifier.hpp"
#include "GeneralisedLinearSpringForce.hpp"
#include "DifferentiatedCellProliferativeType.hpp"
#include "CellAgesWriter.hpp"
#include "CellIdWriter.hpp"
#include "CellProliferativePhasesWriter.hpp"
#include "CellVolumesWriter.hpp"
#include "CellVariablesWriter.hpp"
#include "CellMutationStatesCountWriter.hpp"
#include "CellProliferativePhasesCountWriter.hpp"
#include "CellProliferativeTypesCountWriter.hpp"
#include "SmartPointers.hpp"
#include "PetscSetupAndFinalize.hpp"

The next header file defines a simple stochastic cell-cycle model that includes the functionality for solving each cell's Delta/Notch signalling ODE system at each time step, using information about neighbouring cells through the CellData class. We note that in this simple cell-cycle model, the proliferative status of each cell is unaffected by its Delta/Notch activity; such dependence could easily be introduced given an appropriate model of this coupling.

#include "DeltaNotchCellCycleModel.hpp"

The next header file defines the class that simulates the evolution of a CellPopulation, specialized to deal with updating of the CellData class to deal with Delta-Notch signalling between cells.

The next header defines the simulation class modifier corresponding to the Delta-Notch cell-cycle model. This modifier leads to the CellData cell property being updated at each timestep to deal with Delta-Notch signalling.

#include "DeltaNotchTrackingModifier.hpp"

Having included all the necessary header files, we proceed by defining the test class.

class TestRunningDeltaNotchSimulationsTutorial : public AbstractCellBasedTestSuite
{
public:

Test 1: a vertex-based monolayer with Delta/Notch signalling

In the first test, we demonstrate how to simulate a monolayer that incorporates Delta/Notch signalling, using a vertex-based approach.

    void TestVertexBasedMonolayerWithDeltaNotch() throw (Exception)
    {

We include the next line because Vertex simulations cannot be run in parallel

        EXIT_IF_PARALLEL;

First we create a regular vertex mesh.

        HoneycombVertexMeshGenerator generator(5, 5);
        MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();

We then create some cells, each with a cell-cycle model, DeltaNotchCellCycleModel, which incorporates a Delta/Notch ODE system. In this example we choose to make each cell differentiated, so that no cell division occurs.

        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);

        for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++)
        {
            DeltaNotchCellCycleModel* p_model = new DeltaNotchCellCycleModel();
            p_model->SetDimension(2);

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_diff_type);
            double birth_time = -RandomNumberGenerator::Instance()->ranf()*12.0;
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

Using the vertex mesh and cells, we create a cell-based population object, and specify which results to output to file.

        VertexBasedCellPopulation<2> cell_population(*p_mesh, cells);
        cell_population.AddPopulationWriter<CellMutationStatesCountWriter>();
        cell_population.AddPopulationWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddPopulationWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellProliferativePhasesWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();
        cell_population.AddCellWriter<CellVolumesWriter>();
        cell_population.AddCellWriter<CellVariablesWriter>();

As we are using the CellData class to store the information about each cell required to solve the Delta/Notch ODE system, we must first instantiate this singleton and associate it with the cell population. Note that we set the number of variables to 3. This is because each cell's ODE system comprises two ODEs describing Delta/Notch activity, and an additional 'dummy' ODE with zero reaction term that describes how the mean concentration of Delta among neighbouring cells changes. This latter quantity remains constant for the purposes of solving the ODE system over each time step, but is updated at the end of the time step by a method on DeltaNotchOffLatticeSimulation.

We choose to initialise the concentrations to random levels in each cell.

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("notch", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("delta", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("mean delta", RandomNumberGenerator::Instance()->ranf());
        }

We are now in a position to create and configure the cell-based simulation object, pass a force law to it, and run the simulation. We can make the simulation run for longer to see more patterning by increasing the end time.

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestVertexBasedMonolayerWithDeltaNotch");
        simulator.SetSamplingTimestepMultiple(10);
        simulator.SetEndTime(1.0);

Then, we define the modifier class, which automatically updates the values of Delta and Notch within the cells in CellData and passes it to the simulation.

        MAKE_PTR(DeltaNotchTrackingModifier<2>, p_modifier);
        simulator.AddSimulationModifier(p_modifier);

        MAKE_PTR(NagaiHondaForce<2>, p_force);
        simulator.AddForce(p_force);

This modifier assigns target areas to each cell, which are required by the NagaiHondaForce.

        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);
        simulator.Solve();
    }

To visualize the results, use Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information.

Load the file /tmp/$USER/testoutput/TestVertexBasedMonolayerWithDeltaNotch/results_from_time_0/results.pvd.

Test 2 - a node-based monolayer with Delta/Notch signalling

In the next test we run a similar simulation as before, but this time with node-based 'overlapping spheres' model.

    void TestNodeBasedMonolayerWithDeltaNotch() throw (Exception)
    {

We include the next line because HoneycombMeshGenerator?, used in this test, is not yet implemented in parallel.

        EXIT_IF_PARALLEL;

Most of the code in this test is the same as in the previous test, except we now create a 'nodes-only mesh' and NodeBasedCellPopulation.

        HoneycombMeshGenerator generator(5, 5);
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh();
        NodesOnlyMesh<2> mesh;

The mechanics cut-off length (second argument) is used in this simulation to determine nearest neighbours for the purpose of the Delta/Notch intercellular signalling model.

        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            DeltaNotchCellCycleModel* p_model = new DeltaNotchCellCycleModel();
            p_model->SetDimension(2);

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_diff_type);
            double birth_time = -RandomNumberGenerator::Instance()->ranf()*12.0;
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

        NodeBasedCellPopulation<2> cell_population(mesh, cells);
        cell_population.AddPopulationWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddPopulationWriter<CellMutationStatesCountWriter>();
        cell_population.AddCellWriter<CellIdWriter>();
        cell_population.AddPopulationWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();

We choose to initialise the concentrations to random levels in each cell.

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("notch", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("delta", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("mean delta", RandomNumberGenerator::Instance()->ranf());
        }

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestNodeBasedMonolayerWithDeltaNotch");
        simulator.SetSamplingTimestepMultiple(10);
        simulator.SetEndTime(5.0);

Again we define the modifier class, which automatically updates the values of Delta and Notch within the cells in CellData and passes it to the simulation.

        MAKE_PTR(DeltaNotchTrackingModifier<2>, p_modifier);
        simulator.AddSimulationModifier(p_modifier);

As we are using a node-based cell population, we use an appropriate force law.

        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force);
        p_force->SetCutOffLength(1.5);
        simulator.AddForce(p_force);

        simulator.Solve();
    }

To visualize the results, use Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information

Load the file /tmp/$USER/testoutput/TestNodeBasedMonolayerWithDeltaNotch/results_from_time_0/results.pvd, add a spherical glyph.

};

Code

The full code is given below

File name TestRunningDeltaNotchSimulationsTutorial.hpp

#include <cxxtest/TestSuite.h>
#include "CheckpointArchiveTypes.hpp"
#include "AbstractCellBasedTestSuite.hpp"
#include "HoneycombMeshGenerator.hpp"
#include "HoneycombVertexMeshGenerator.hpp"
#include "NodeBasedCellPopulation.hpp"
#include "OffLatticeSimulation.hpp"
#include "VertexBasedCellPopulation.hpp"
#include "NagaiHondaForce.hpp"
#include "SimpleTargetAreaModifier.hpp"
#include "GeneralisedLinearSpringForce.hpp"
#include "DifferentiatedCellProliferativeType.hpp"
#include "CellAgesWriter.hpp"
#include "CellIdWriter.hpp"
#include "CellProliferativePhasesWriter.hpp"
#include "CellVolumesWriter.hpp"
#include "CellVariablesWriter.hpp"
#include "CellMutationStatesCountWriter.hpp"
#include "CellProliferativePhasesCountWriter.hpp"
#include "CellProliferativeTypesCountWriter.hpp"
#include "SmartPointers.hpp"
#include "PetscSetupAndFinalize.hpp"
#include "DeltaNotchCellCycleModel.hpp"
#include "DeltaNotchTrackingModifier.hpp"

class TestRunningDeltaNotchSimulationsTutorial : public AbstractCellBasedTestSuite
{
public:

    void TestVertexBasedMonolayerWithDeltaNotch() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        HoneycombVertexMeshGenerator generator(5, 5);
        MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();

        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);

        for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++)
        {
            DeltaNotchCellCycleModel* p_model = new DeltaNotchCellCycleModel();
            p_model->SetDimension(2);

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_diff_type);
            double birth_time = -RandomNumberGenerator::Instance()->ranf()*12.0;
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

        VertexBasedCellPopulation<2> cell_population(*p_mesh, cells);
        cell_population.AddPopulationWriter<CellMutationStatesCountWriter>();
        cell_population.AddPopulationWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddPopulationWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellProliferativePhasesWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();
        cell_population.AddCellWriter<CellVolumesWriter>();
        cell_population.AddCellWriter<CellVariablesWriter>();

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("notch", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("delta", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("mean delta", RandomNumberGenerator::Instance()->ranf());
        }

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestVertexBasedMonolayerWithDeltaNotch");
        simulator.SetSamplingTimestepMultiple(10);
        simulator.SetEndTime(1.0);

        MAKE_PTR(DeltaNotchTrackingModifier<2>, p_modifier);
        simulator.AddSimulationModifier(p_modifier);

        MAKE_PTR(NagaiHondaForce<2>, p_force);
        simulator.AddForce(p_force);

        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);
        simulator.Solve();
    }

    void TestNodeBasedMonolayerWithDeltaNotch() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        HoneycombMeshGenerator generator(5, 5);
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh();
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            DeltaNotchCellCycleModel* p_model = new DeltaNotchCellCycleModel();
            p_model->SetDimension(2);

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_diff_type);
            double birth_time = -RandomNumberGenerator::Instance()->ranf()*12.0;
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

        NodeBasedCellPopulation<2> cell_population(mesh, cells);
        cell_population.AddPopulationWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddPopulationWriter<CellMutationStatesCountWriter>();
        cell_population.AddCellWriter<CellIdWriter>();
        cell_population.AddPopulationWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("notch", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("delta", RandomNumberGenerator::Instance()->ranf());
            cell_iter->GetCellData()->SetItem("mean delta", RandomNumberGenerator::Instance()->ranf());
        }

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestNodeBasedMonolayerWithDeltaNotch");
        simulator.SetSamplingTimestepMultiple(10);
        simulator.SetEndTime(5.0);

        MAKE_PTR(DeltaNotchTrackingModifier<2>, p_modifier);
        simulator.AddSimulationModifier(p_modifier);

        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force);
        p_force->SetCutOffLength(1.5);
        simulator.AddForce(p_force);

        simulator.Solve();
    }
};