#include <cxxtest/TestSuite.h>
// Must be included before any other cell_based headers
#include "CellBasedSimulationArchiver.hpp"
#include "SmartPointers.hpp"
#include "CylindricalHoneycombVertexMeshGenerator.hpp"
#include "CylindricalHoneycombMeshGenerator.hpp"
#include "PottsMeshGenerator.hpp"
#include "Cylindrical2dNodesOnlyMesh.hpp"
#include "CellsGenerator.hpp"
#include "SimpleWntContactInhibitionCellCycleModel.hpp"
#include "WntConcentration.hpp"
#include "MeshBasedCellPopulationWithGhostNodes.hpp"
#include "NodeBasedCellPopulation.hpp"
#include "PottsBasedCellPopulation.hpp"
#include "VertexBasedCellPopulation.hpp"
#include "CellProliferativeTypesCountWriter.hpp"
#include "CellIdWriter.hpp"
#include "CellVolumesWriter.hpp"
#include "CellAncestorWriter.hpp"
#include "OffLatticeSimulation.hpp"
#include "OnLatticeSimulation.hpp"
#include "NagaiHondaForce.hpp"
#include "RepulsionForce.hpp"
#include "DiffusionCaUpdateRule.hpp"
#include "VolumeConstraintPottsUpdateRule.hpp"
#include "AdhesionPottsUpdateRule.hpp"
#include "SurfaceAreaConstraintPottsUpdateRule.hpp"
#include "SimpleTargetAreaModifier.hpp"
#include "VolumeTrackingModifier.hpp"
#include "PlaneBasedCellKiller.hpp"
#include "PlaneBoundaryCondition.hpp"
#include "CryptShovingCaBasedDivisionRule.hpp"
#include "AbstractCellBasedWithTimingsTestSuite.hpp"
#include "PetscSetupAndFinalize.hpp"
#include "Warnings.hpp"
static const double M_END_STEADY_STATE = 100; //100
static const double M_END_TIME = 1100; //1100
static const double M_CRYPT_DIAMETER = 16;
static const double M_CRYPT_LENGTH = 12;
static const double M_CONTACT_INHIBITION_LEVEL = 0.8;
class TestCylindricalCryptLiteratePaper : public AbstractCellBasedWithTimingsTestSuite
{
private:
void GenerateCells(unsigned num_cells, std::vector<CellPtr>& rCells, double equilibriumVolume, double quiescentVolumeFraction)
{
double typical_cell_cycle_duration = 12.0;
boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>());
boost::shared_ptr<AbstractCellProperty> p_cell_type(CellPropertyRegistry::Instance()->Get<TransitCellProliferativeType>());
for (unsigned i=0; i<num_cells; i++)
{
SimpleWntContactInhibitionCellCycleModel* p_model = new SimpleWntContactInhibitionCellCycleModel();
p_model->SetDimension(2);
p_model->SetEquilibriumVolume(equilibriumVolume);
p_model->SetQuiescentVolumeFraction(quiescentVolumeFraction);
p_model->SetWntThreshold(0.5);
CellPtr p_cell(new Cell(p_state, p_model));
p_cell->SetCellProliferativeType(p_cell_type);
double birth_time = - RandomNumberGenerator::Instance()->ranf() * typical_cell_cycle_duration;
p_cell->SetBirthTime(birth_time);
// Set Target Area so dont need to use a growth model in vertex simulations
p_cell->GetCellData()->SetItem("target area", 1.0);
rCells.push_back(p_cell);
}
}
public:
void TestCaBasedCrypt()
{
// Create a simple 2D PottsMesh (periodic in x)
PottsMeshGenerator<2> generator(M_CRYPT_DIAMETER, 0, 0, M_CRYPT_LENGTH*3, 0, 0, 1, 0, 0, false, true);
PottsMesh<2>* p_mesh = generator.GetMesh();
// Specify where cells lie
std::vector<unsigned> location_indices;
for (unsigned index=0; index<(unsigned)M_CRYPT_DIAMETER*(unsigned)M_CRYPT_LENGTH; index++)
{
location_indices.push_back(index);
}
// Create cells
std::vector<CellPtr> cells;
GenerateCells(location_indices.size(),cells,1.0,M_CONTACT_INHIBITION_LEVEL); //Mature volume = 1 LS
// Create cell population
CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices);
cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
cell_population.AddCellWriter<CellVolumesWriter>();
cell_population.AddCellWriter<CellIdWriter>();
cell_population.AddCellWriter<CellAncestorWriter>();
// Create an instance of a Wnt concentration
WntConcentration<2>::Instance()->SetType(LINEAR);
WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
WntConcentration<2>::Instance()->SetCryptLength(M_CRYPT_LENGTH);
// Set up cell-based simulation
OnLatticeSimulation<2> simulator(cell_population);
simulator.SetOutputDirectory("CylindricalCrypt/Ca");
simulator.SetDt(0.01);
simulator.SetSamplingTimestepMultiple(100);
simulator.SetEndTime(M_END_STEADY_STATE);
simulator.SetOutputDivisionLocations(true);
simulator.SetOutputCellVelocities(true);
// Add Volume tracking modifier
MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
simulator.AddSimulationModifier(p_modifier);
// Add Division Rule
boost::shared_ptr<AbstractCaBasedDivisionRule<2> > p_division_rule(new CryptShovingCaBasedDivisionRule());
cell_population.SetCaBasedDivisionRule(p_division_rule);
// Sloughing killer
MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, M_CRYPT_LENGTH*unit_vector<double>(2,1), unit_vector<double>(2,1)));
simulator.AddCellKiller(p_killer);
// Run simulation
simulator.Solve();
// Mark Ancestors
simulator.SetEndTime(M_END_TIME);
simulator.rGetCellPopulation().SetCellAncestorsToLocationIndices();
// Run simulation to new end time
simulator.Solve();
// Clear singletons
WntConcentration<2>::Instance()->Destroy();
}
void TestPottsBasedCrypt()
{
unsigned cell_width = 4;
// Create a simple 2D PottsMesh (periodic in x)
PottsMeshGenerator<2> generator( M_CRYPT_DIAMETER*cell_width, M_CRYPT_DIAMETER, cell_width, (M_CRYPT_LENGTH+2)*cell_width, M_CRYPT_LENGTH, cell_width, 1, 1, 1, true, true); //Dtart from bottom left and periodic
PottsMesh<2>* p_mesh = generator.GetMesh();
// Create cells
std::vector<CellPtr> cells;
GenerateCells(p_mesh->GetNumElements(),cells,cell_width*cell_width,M_CONTACT_INHIBITION_LEVEL); // mature volume = 16.0 LSs
// Create cell population
PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);
cell_population.SetTemperature(0.1);
cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
cell_population.AddCellWriter<CellVolumesWriter>();
cell_population.AddCellWriter<CellIdWriter>();
cell_population.AddCellWriter<CellAncestorWriter>();
// Set the Temperature
cell_population.SetTemperature(0.1); //Default is 0.1
// Create an instance of a Wnt concentration
WntConcentration<2>::Instance()->SetType(LINEAR);
WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
WntConcentration<2>::Instance()->SetCryptLength(M_CRYPT_LENGTH*cell_width);
// Set up cell-based simulation
OnLatticeSimulation<2> simulator(cell_population);
simulator.SetOutputDirectory("CylindricalCrypt/Potts");
simulator.SetDt(0.01);
simulator.SetSamplingTimestepMultiple(100);
simulator.SetEndTime(M_END_STEADY_STATE);
simulator.SetOutputDivisionLocations(true);
simulator.SetOutputCellVelocities(true);
// Add volume tracking modifier
MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
simulator.AddSimulationModifier(p_modifier);
// Sloughing killer
MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, cell_width*M_CRYPT_LENGTH*unit_vector<double>(2,1), unit_vector<double>(2,1)));
simulator.AddCellKiller(p_killer);
// Create update rules and pass to the simulation
MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
p_volume_constraint_update_rule->SetMatureCellTargetVolume(16); // i.e 4x4 cells
p_volume_constraint_update_rule->SetDeformationEnergyParameter(0.1);
simulator.AddUpdateRule(p_volume_constraint_update_rule);
MAKE_PTR(SurfaceAreaConstraintPottsUpdateRule<2>, p_surface_constraint_update_rule);
p_surface_constraint_update_rule->SetMatureCellTargetSurfaceArea(16); // i.e 4x4 cells
p_surface_constraint_update_rule->SetDeformationEnergyParameter(0.01);
simulator.AddUpdateRule(p_surface_constraint_update_rule);
MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule);
p_adhesion_update_rule->SetCellCellAdhesionEnergyParameter(0.1);
p_adhesion_update_rule->SetCellBoundaryAdhesionEnergyParameter(0.2);
simulator.AddUpdateRule(p_adhesion_update_rule);
// Run simulation
simulator.Solve();
// Mark Ancestors
simulator.SetEndTime(M_END_TIME);
simulator.rGetCellPopulation().SetCellAncestorsToLocationIndices();
// Run simulation to new end time
simulator.Solve();
// Clear singletons
WntConcentration<2>::Instance()->Destroy();
}
void TestNodeBasedCrypt()
{
// Create a simple mesh
HoneycombMeshGenerator generator(M_CRYPT_DIAMETER, M_CRYPT_LENGTH, 0);
TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();
double cut_off_length = 1.5; //this is the default
// Convert this to a Cylindrical2dNodesOnlyMesh
Cylindrical2dNodesOnlyMesh* p_mesh = new Cylindrical2dNodesOnlyMesh(M_CRYPT_DIAMETER);
p_mesh->ConstructNodesWithoutMesh(*p_generating_mesh,2.0); // So factor of 16
// Create cells
std::vector<CellPtr> cells;
GenerateCells(p_mesh->GetNumNodes(), cells, M_PI*0.25,M_CONTACT_INHIBITION_LEVEL); // mature volume: M_PI*0.25 as r=0.5
// Create a node-based cell population
NodeBasedCellPopulation<2> cell_population(*p_mesh, cells);
cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
cell_population.AddCellWriter<CellVolumesWriter>();
cell_population.AddCellWriter<CellIdWriter>();
cell_population.AddCellWriter<CellAncestorWriter>();
for (unsigned index = 0; index < cell_population.rGetMesh().GetNumNodes(); index++)
{
cell_population.rGetMesh().GetNode(index)->SetRadius(0.5);
}
// Create an instance of a Wnt concentration
WntConcentration<2>::Instance()->SetType(LINEAR);
WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
WntConcentration<2>::Instance()->SetCryptLength(M_CRYPT_LENGTH);
// Create simulation from cell population
OffLatticeSimulation<2> simulator(cell_population);
simulator.SetDt(1.0/200.0);
simulator.SetSamplingTimestepMultiple(200);
simulator.SetEndTime(M_END_STEADY_STATE);
simulator.SetOutputDirectory("CylindricalCrypt/Node");
simulator.SetOutputDivisionLocations(true);
simulator.SetOutputCellVelocities(true);
// Add volume tracking modifier
MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
simulator.AddSimulationModifier(p_modifier);
// Create a force law and pass it to the simulation
MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
p_linear_force->SetMeinekeSpringStiffness(50.0);
p_linear_force->SetCutOffLength(cut_off_length);
simulator.AddForce(p_linear_force);
// Solid base boundary condition
MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bcs, (&cell_population, zero_vector<double>(2), -unit_vector<double>(2,1)));
p_bcs->SetUseJiggledNodesOnPlane(true);
simulator.AddCellPopulationBoundaryCondition(p_bcs);
// Sloughing killer
MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, (M_CRYPT_LENGTH-0.5)*unit_vector<double>(2,1), unit_vector<double>(2,1)));
simulator.AddCellKiller(p_killer);
// Run simulation
simulator.Solve();
// Mark Ancestors
simulator.SetEndTime(M_END_TIME);
simulator.rGetCellPopulation().SetCellAncestorsToLocationIndices();
// Run simulation to new end time
simulator.Solve();
// Clear memory
delete p_mesh;
// Clear singletons
WntConcentration<2>::Instance()->Destroy();
}
void TestMeshBasedCrypt()
{
// Create mesh
unsigned thickness_of_ghost_layer = 2;
CylindricalHoneycombMeshGenerator generator(M_CRYPT_DIAMETER, M_CRYPT_LENGTH, thickness_of_ghost_layer);
Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();
// Get location indices corresponding to real cells
std::vector<unsigned> location_indices = generator.GetCellLocationIndices();
// Create cells
std::vector<CellPtr> cells;
GenerateCells(location_indices.size(),cells,sqrt(3.0)/2.0,M_CONTACT_INHIBITION_LEVEL); //mature_volume = sqrt(3.0)/2.0
// Create tissue
MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices);
cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
cell_population.AddCellWriter<CellVolumesWriter>();
cell_population.AddCellWriter<CellIdWriter>();
cell_population.AddCellWriter<CellAncestorWriter>();
// Create an instance of a Wnt concentration
WntConcentration<2>::Instance()->SetType(LINEAR);
WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
WntConcentration<2>::Instance()->SetCryptLength(M_CRYPT_LENGTH);
// Create simulation from cell population
OffLatticeSimulation<2> simulator(cell_population);
simulator.SetDt(1.0/200.0);
simulator.SetSamplingTimestepMultiple(200);
simulator.SetEndTime(M_END_STEADY_STATE);
simulator.SetOutputDirectory("CylindricalCrypt/Mesh");
simulator.SetOutputDivisionLocations(true);
simulator.SetOutputCellVelocities(true);
// Add volume tracking Modifier
MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
simulator.AddSimulationModifier(p_modifier);
// Create a force law and pass it to the simulation
MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
p_linear_force->SetMeinekeSpringStiffness(50.0);
simulator.AddForce(p_linear_force);
// Solid base boundary condition
MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bcs, (&cell_population, zero_vector<double>(2), -unit_vector<double>(2,1)));
p_bcs->SetUseJiggledNodesOnPlane(true);
simulator.AddCellPopulationBoundaryCondition(p_bcs);
// Sloughing killer
MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, (M_CRYPT_LENGTH-0.5)*unit_vector<double>(2,1), unit_vector<double>(2,1)));
simulator.AddCellKiller(p_killer);
// Run simulation
simulator.Solve();
// Mark Ancestors
simulator.SetEndTime(M_END_TIME);
simulator.rGetCellPopulation().SetCellAncestorsToLocationIndices();
// Run simulation to new end time
simulator.Solve();
// Clear singletons
WntConcentration<2>::Instance()->Destroy();
}
void TestVertexBasedCrypt()
{
// Create mesh
CylindricalHoneycombVertexMeshGenerator generator(M_CRYPT_DIAMETER, M_CRYPT_LENGTH, true);
Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh();
p_mesh->SetCellRearrangementThreshold(0.1);
// Create cells
std::vector<CellPtr> cells;
GenerateCells(p_mesh->GetNumElements(),cells,1.0,M_CONTACT_INHIBITION_LEVEL); //mature_volume = 1.0
// Create tissue
VertexBasedCellPopulation<2> cell_population(*p_mesh, cells);
cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
cell_population.AddCellWriter<CellVolumesWriter>();
cell_population.AddCellWriter<CellIdWriter>();
// Create an instance of a Wnt concentration
WntConcentration<2>::Instance()->SetType(LINEAR);
WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
WntConcentration<2>::Instance()->SetCryptLength(M_CRYPT_LENGTH);
// Create crypt simulation from cell population
OffLatticeSimulation<2> simulator(cell_population);
simulator.SetDt(1.0/200.0);
simulator.SetSamplingTimestepMultiple(200);
simulator.SetEndTime(M_END_STEADY_STATE);
simulator.SetOutputDirectory("CylindricalCrypt/Vertex");
simulator.SetOutputDivisionLocations(true);
simulator.SetOutputCellVelocities(true);
cell_population.AddCellWriter<CellAncestorWriter>();
// Add volume tracking modifier
MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
simulator.AddSimulationModifier(p_modifier);
// Create Forces and pass to simulation NOTE : these are not the default ones and chosen to give a stable growing monolayer
MAKE_PTR(NagaiHondaForce<2>, p_force);
p_force->SetNagaiHondaDeformationEnergyParameter(50.0);
p_force->SetNagaiHondaMembraneSurfaceEnergyParameter(1.0);
p_force->SetNagaiHondaCellCellAdhesionEnergyParameter(1.0);
p_force->SetNagaiHondaCellBoundaryAdhesionEnergyParameter(10.0);
simulator.AddForce(p_force);
// Solid base Boundary condition
MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bcs, (&cell_population, zero_vector<double>(2), -unit_vector<double>(2,1)));
p_bcs->SetUseJiggledNodesOnPlane(true);
simulator.AddCellPopulationBoundaryCondition(p_bcs);
// Sloughing killer
MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, M_CRYPT_LENGTH*unit_vector<double>(2,1), unit_vector<double>(2,1)));
simulator.AddCellKiller(p_killer);
// Run simulation
simulator.Solve();
// Mark Ancestors
simulator.SetEndTime(M_END_TIME);
simulator.rGetCellPopulation().SetCellAncestorsToLocationIndices();
// Run simulation to new end time
simulator.Solve();
// Clear singletons
WntConcentration<2>::Instance()->Destroy();
Warnings::Instance()->QuietDestroy();
}
};