void TestParabolicConstructor() { // Create PDE and boundary condition objects MAKE_PTR_ARGS(UniformSourceParabolicPde<2>, p_pde, (-0.1)); MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0)); // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE ChastePoint<2> lower(-10.0, -10.0); ChastePoint<2> upper(10.0, 10.0); MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper)); // Create a PDE modifier and set the name of the dependent variable in the PDE MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid, 2.0)); p_pde_modifier->SetDependentVariableName("averaged quantity"); // Test that member variables are initialised correctly TS_ASSERT_EQUALS(p_pde_modifier->rGetDependentVariableName(), "averaged quantity"); // Check mesh TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumNodes(),121u); TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumBoundaryNodes(),40u); TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumElements(),200u); TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumBoundaryElements(),40u); ChasteCuboid<2> bounding_box = p_pde_modifier->mpFeMesh->CalculateBoundingBox(); TS_ASSERT_DELTA(bounding_box.rGetUpperCorner()[0],10,1e-5); TS_ASSERT_DELTA(bounding_box.rGetUpperCorner()[1],10,1e-5); TS_ASSERT_DELTA(bounding_box.rGetLowerCorner()[0],-10,1e-5); TS_ASSERT_DELTA(bounding_box.rGetLowerCorner()[1],-10,1e-5); // Coverage TS_ASSERT_EQUALS(p_pde_modifier->GetOutputGradient(),false); // Defaults to false p_pde_modifier->SetOutputGradient(true); TS_ASSERT_EQUALS(p_pde_modifier->GetOutputGradient(),true); }
CellPtr Cell::Divide() { // Check we're allowed to divide assert(!IsDead()); assert(mCanDivide); mCanDivide = false; // Reset properties of parent cell mpCellCycleModel->ResetForDivision(); mpSrnModel->ResetForDivision(); // Create copy of cell property collection to modify for daughter cell CellPropertyCollection daughter_property_collection = mCellPropertyCollection; // Remove the CellId from the daughter cell, as a new one will be assigned in the constructor daughter_property_collection.RemoveProperty<CellId>(); // Copy all cell data (note we create a new object not just copying the pointer) assert(daughter_property_collection.HasPropertyType<CellData>()); // Get the existing copy of the cell data and remove it from the daughter cell boost::shared_ptr<CellData> p_cell_data = GetCellData(); daughter_property_collection.RemoveProperty(p_cell_data); // Create a new cell data object using the copy constructor and add this to the daughter cell MAKE_PTR_ARGS(CellData, p_daughter_cell_data, (*p_cell_data)); daughter_property_collection.AddProperty(p_daughter_cell_data); // Copy all cell Vec data (note we create a new object not just copying the pointer) if (daughter_property_collection.HasPropertyType<CellVecData>()) { // Get the existing copy of the cell data and remove it from the daughter cell boost::shared_ptr<CellVecData> p_cell_vec_data = GetCellVecData(); daughter_property_collection.RemoveProperty(p_cell_vec_data); // Create a new cell data object using the copy constructor and add this to the daughter cell MAKE_PTR_ARGS(CellVecData, p_daughter_cell_vec_data, (*p_cell_vec_data)); daughter_property_collection.AddProperty(p_daughter_cell_vec_data); } // Create daughter cell with modified cell property collection CellPtr p_new_cell(new Cell(GetMutationState(), mpCellCycleModel->CreateCellCycleModel(), mpSrnModel->CreateSrnModel(), false, daughter_property_collection)); // Initialise properties of daughter cell p_new_cell->GetCellCycleModel()->InitialiseDaughterCell(); p_new_cell->GetSrnModel()->InitialiseDaughterCell(); // Set the daughter cell to inherit the apoptosis time of the parent cell p_new_cell->SetApoptosisTime(mApoptosisTime); return p_new_cell; }
OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OffLatticeSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation, bool deleteCellPopulationInDestructor, bool initialiseCells) : AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells) { if (!dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation)) { EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation."); } // Different time steps are used for cell-centre and vertex-based simulations if (bool(dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))) { this->mDt = 1.0/120.0; // 30 seconds } else if (bool(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation))) { this->mDt = 0.002; // smaller time step required for convergence/stability // For VertexBasedCellPopulations we automatically add a T2SwapCellKiller. In order to inhibit T2 swaps // the user needs to set the threshold for T2 swaps in the mesh to 0. VertexBasedCellPopulation<SPACE_DIM>* p_vertex_based_cell_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation); MAKE_PTR_ARGS(T2SwapCellKiller<SPACE_DIM>, T2_swap_cell_killer, (p_vertex_based_cell_population)); this->AddCellKiller(T2_swap_cell_killer); } else { // All classes derived from AbstractOffLatticeCellPopulation are covered by the above (except user-derived classes), // i.e. if you want to use this class with your own subclass of AbstractOffLatticeCellPopulation, then simply // comment out the line below NEVER_REACHED; } }
OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OffLatticeSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation, bool deleteCellPopulationInDestructor, bool initialiseCells) : AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells) { if (!dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation)) { EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation."); } // Different time steps are used for cell-centre and vertex-based simulations if (dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation)) { this->mDt = 1.0/120.0; // 30 seconds } else { assert(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation)); this->mDt = 0.002; // smaller time step required for convergence/stability // For VertexBasedCellPopulations we automatically add a T2SwapCellKiller. In order to inhibit T2 swaps // the user needs to set the threshold for T2 swaps in the mesh to 0. VertexBasedCellPopulation<SPACE_DIM>* p_vertex_based_cell_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation); MAKE_PTR_ARGS(T2SwapCellKiller<SPACE_DIM>, T2_swap_cell_killer, (p_vertex_based_cell_population)); this->AddCellKiller(T2_swap_cell_killer); } }
void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetCellAncestorsToLocationIndices() { for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter) { MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()])); cell_iter->SetAncestor(p_cell_ancestor); } }
/* EMPTYLINE * * * == Test 1 - create a vertex-based crypt simulation == * * EMPTYLINE * * The first test generates a crypt, in which we use a cylindrical vertex mesh, * give each cell a fixed cell-cycle model, and enforce sloughing at the top of * the crypt. */ void TestVertexBasedCrypt() throw(Exception) { /* Create a cylindrical mesh, and get the cell location indices. To enforce * periodicity at the left and right hand sides of the mesh, we use a subclass * called {{{Cylindrical2dMesh}}}, which has extra methods for maintaining * periodicity. */ CylindricalHoneycombVertexMeshGenerator generator(6, 9); Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh(); /* Having created a mesh, we now create a {{{std::vector}}} of {{{CellPtr}}}s. * To do this, we the `CryptCellsGenerator` helper class, which is templated over the type * of cell model required (here {{{FixedDurationGenerationBasedCellCycleModel}}}) * and the dimension. We create an empty vector of cells and pass this into the * method along with the mesh. The third argument 'true' indicates that the cells * should be assigned random birth times, to avoid synchronous division. The * {{{cells}}} vector is populated once the method {{{Generate}}} is * called. * The last four arguments represent the height below which cells belong to generations 0, * 1, 2, 3 and 4, respectively. */ std::vector<CellPtr> cells; CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true, 1.0, 2.0, 3.0, 4.0); /* Create a cell population, as before. */ VertexBasedCellPopulation<2> crypt(*p_mesh, cells); /* Create a simulator as before (except setting a different output directory). */ CryptSimulation2d simulator(crypt); simulator.SetOutputDirectory("VertexCrypt"); simulator.SetEndTime(0.1); /* Before running the simulation, we add a one or more force laws, which determine the mechanics of * the cell population. For this test, we use a {{{NagaiHondaForce}}}. */ MAKE_PTR(NagaiHondaForce<2>, p_force); simulator.AddForce(p_force); /* The {{{NagaiHondaForce}}} requires us to add a child class of {{{AbstractTargetAreaModifier}}} to the simulation. * This modifier assigns and updates target areas to each cell throughout the simulation. The target * areas are in turn used by the force law to determine the pressure forces on each vertex. */ MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); /* Before running the simulation, we add a cell killer. This object * dictates conditions under which cells die. For this test, we use * a {{{SloughingCellKiller}}}, which kills cells above a certain height. */ double crypt_length = 6.0; MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length)); simulator.AddCellKiller(p_killer); /* To run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); }
void TestStandardResultForArchivingTestsBelow() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationStandardResult"); simulator.SetEndTime(2.5); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); // Solve simulator.Solve(); // Check some results mNode3x = 3.0454; mNode3y = 0.0000; mNode4x = 4.0468; mNode4y = 0.0101; std::vector<double> node_3_location = simulator.GetNodeLocation(3); TS_ASSERT_DELTA(node_3_location[0], mNode3x, 1e-4); TS_ASSERT_DELTA(node_3_location[1], mNode3y, 1e-4); std::vector<double> node_4_location = simulator.GetNodeLocation(4); TS_ASSERT_DELTA(node_4_location[0], mNode4x, 1e-4); TS_ASSERT_DELTA(node_4_location[1], mNode4y, 1e-4); }
// Testing Save() void TestSave() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel // Create a simple mesh unsigned num_cells_depth = 5; unsigned num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad"); simulator.SetEndTime(0.1); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); /* * For more thorough testing of serialization, we 'turn on' adaptivity. * Note that this has no effect on the numerical results, since the * conditions under which the time step would be adapted are not invoked * in this example. */ boost::shared_ptr<AbstractNumericalMethod<2,2> > p_method(new ForwardEulerNumericalMethod<2,2>()); p_method->SetUseAdaptiveTimestep(true); simulator.SetNumericalMethod(p_method); // Solve simulator.Solve(); // Save the results CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator); }
/* * The results may be visualized using {{{Visualize2dCentreCells}}} as described in the * previous test, with the results directory changed from {{{CellBasedDemo5}}} to {{{CellBasedDemo6}}}. * * == Test 7 - basic Potts-based simulation == * * In the final test we show how to modify the earlier tests (using off lattice models) to implement a 'Potts-based' simulation, * in which cells are represented by collections of sites on a fixed lattice. */ void TestPottsBasedMonolayer() throw (Exception) { /* In common with the off lattice simulations we begin by creating a mesh. Here we use the {{{PottsMeshGenerator}}} * class to generate a {{{PottsMesh}}} each element in the mesh is a collection of lattice sites (represented by nodes at their centres). * All the connectivity between lattice sites is defined by the {{{PottsMeshGenerator}}}, * and there are arguments to make the domains periodic. */ PottsMeshGenerator<2> generator(20, 2, 4, 20, 2, 4); //**Changed**// PottsMesh<2>* p_mesh = generator.GetMesh(); //**Changed**// /* We generate one cell for each element as in vertex based simulations.*/ std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type); /* As we have a {{{PottsMesh}}} we use a {{{PottsBasedCellPopulation}}}. Note here we also change the * "temperature" of the Potts simulation to make cells more motile.*/ PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);//**Changed**// cell_population.SetTemperature(1.0); /* As a Potts simulation is restricted to a lattice we create a {{{OnSimulation}}} object and pass in the {{{CellPopulation}}} in much the same * way as an {{{OffLatticeSimulation}}} in the above examples. We also set some * options on the simulation like output directory and end time. */ OnLatticeSimulation<2> simulator(cell_population);//**Changed**// simulator.SetOutputDirectory("CellBasedDemo7"); //**Changed**// simulator.SetEndTime(20.0); /* In order to specify how cells move around we create "shared pointers" to * {{{UpdateRule}}} objects and pass them to the {{{OnLatticeSimulation}}}. * This is analogous to {{{Forces}}} in earlier examples. */ MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule); //**Changed**// simulator.AddPottsUpdateRule(p_volume_constraint_update_rule); //**Changed**// MAKE_PTR(SurfaceAreaConstraintPottsUpdateRule<2>, p_surface_area_update_rule); //**Changed**// simulator.AddPottsUpdateRule(p_surface_area_update_rule); //**Changed**// MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule); //**Changed**// simulator.AddPottsUpdateRule(p_adhesion_update_rule); //**Changed**// /* We can add {{{CellKillers}}} as before.*/ MAKE_PTR_ARGS(RandomCellKiller<2>, p_cell_killer, (&cell_population, 0.01)); simulator.AddCellKiller(p_cell_killer); /* Again we run the simulation by calling the {{{Solve}}} method.*/ simulator.Solve(); /* The next two lines are for test purposes only and are not part of this tutorial. */ TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 16u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10); }
/* * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory, * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dVertexCells /tmp/$USER/testoutput/CellBasedDemo1/results_from_time_0}}}. * We may have to do: {{{javac Visualize2dVertexCells.java}}} beforehand to create the * java executable. * * EMPTYLINE * * The {{{make_a_movie}}} script can be used to generate a video based on the results of your simulation. * To do this, first visualize the results using {{{Visualize2dVertexCells}}} as described above. Click * on the box marked "Output" and play through the whole simulation to generate a sequence of {{{.png}}} * images, one for each time step. Next, still in the {{{anim}}} folder, do: {{{./make_a_movie}}}. * This reads in the {{{.png}}} files and creates a video file called {{{simulation.mpeg}}}. * * EMPTYLINE * * Results can also be visualized using Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information. * * EMPTYLINE * * == Test 2 - basic node-based simulation == * * We next show how to modify the previous test to implement a 'node-based' simulation, * in which cells are represented by overlapping spheres (actually circles, since we're * in 2D). */ void TestNodeBasedMonolayer() throw (Exception) { /* We now need to create a {{{NodesOnlyMesh}}} we do this by first creating a {{{MutableMesh}}} * and passing this to a helper method {{{ConstructNodesWithoutMesh}}} along with a interaction cut off length * that defines the connectivity in the mesh. */ HoneycombMeshGenerator generator(2, 2); //**Changed**// MutableMesh<2,2>* p_generating_mesh = generator.GetMesh(); //**Changed**// NodesOnlyMesh<2> mesh; //**Changed**// mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); //**Changed**// /* We create the cells as before, only this time we need one cell per node.*/ std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); //**Changed**// /* This time we create a {{{NodeBasedCellPopulation}}} as we are using a {{{NodesOnlyMesh}}}.*/ NodeBasedCellPopulation<2> cell_population(mesh, cells);//**Changed**// /* We create an {{{OffLatticeSimulation}}} object as before, all we change is the output directory * and output results more often as a larger default timestep is used for these simulations. */ OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("CellBasedDemo2"); //**Changed**// simulator.SetSamplingTimestepMultiple(12); //**Changed**// simulator.SetEndTime(20.0); /* We use a different {{{Force}}} which is suitable for node based simulations. */ MAKE_PTR(RepulsionForce<2>, p_force); //**Changed**// simulator.AddForce(p_force); /* In all types of simulation you may specify how cells are removed from the simulation by specifying * a {{{CellKiller}}}. You create these in the same was as the {{{Force}}} and pass them to the {{{CellBasedSimulation}}}. * Note that here the constructor for {{{RandomCellKiller}}} requires some arguments to be passed to it, therefore we use the * {{{MAKE_PTR_ARGS}}} macro. */ MAKE_PTR_ARGS(RandomCellKiller<2>, p_cell_killer, (&cell_population, 0.01)); //**Changed**// simulator.AddCellKiller(p_cell_killer); /* Again we call the {{{Solve}}} method on the simulation to run the simulation.*/ simulator.Solve(); /* The next two lines are for test purposes only and are not part of this tutorial. * Again, we are checking that we reached the end time of the simulation * with the correct number of cells. */ TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 7u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10); }
/* * EMPTYLINE * * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory, * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dVertexCells /tmp/$USER/testoutput/VertexCrypt/results_from_time_0}}}. * You may have to do: {{{javac Visualize2dVertexCells.java}}} beforehand to create the * java executable. * * EMPTYLINE * * When we visualize the results, we should see three colours of cells: a row of blue stem cells, 3 rows of yellow transit * cells, and 5 rows of pink differentiated cells. Cells above 6.0 will be sloughed off immediately. * * EMPTYLINE * * == Test 2 - create a vertex-based crypt simulation with a simple wnt dependent cell-cycle model == * * EMPTYLINE * * The next test generates a crypt, in which we use a cylindrical vertex mesh, and * impose a linearly decreasing concentration gradient of Wnt. Cells detect the level of Wnt * at their centre and those that are in a region of sufficient Wnt are defined to be transit cells, * whilst those above this Wnt threshold are defined to be differentiated. The cell cycle length of * transit cells is then assigned randomly from a uniform distribution. */ void TestVertexBasedCryptWithSimpleWntCellCycleModel() throw(Exception) { /* Create a cylindrical mesh, and get the cell location indices, as before. */ CylindricalHoneycombVertexMeshGenerator generator(6, 9); Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh(); /* Create a {{{std::vector}}} of {{{CellPtr}}}s. * Generate cells, which are assigned a {{{SimpleWntCellCycleModel}}} using * the {{{CryptCellsGenerator}}}. The final boolean argument 'true' indicates * to assign randomly chosen birth times. */ std::vector<CellPtr> cells; CryptCellsGenerator<SimpleWntCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); /* Create a cell population, as before. */ VertexBasedCellPopulation<2> crypt(*p_mesh, cells); /* Define the crypt length; this will be used for sloughing and calculating the Wnt gradient. */ double crypt_length = 6.0; /* Set up a {{{WntConcentration}}} object, as in UserTutorials/RunningMeshBasedCryptSimulations. */ WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetCellPopulation(crypt); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); /* Create a simulator as before, and add a force law, the target area modifier and a sloughing cell killer to it. */ CryptSimulation2d simulator(crypt); simulator.SetOutputDirectory("VertexCryptWithSimpleWntCellCycleModel"); simulator.SetEndTime(0.1); MAKE_PTR(NagaiHondaForce<2>, p_force); simulator.AddForce(p_force); MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length)); simulator.AddCellKiller(p_killer); /* Here we impose a boundary condition at the base: that cells * at the bottom of the crypt are repelled if they move past 0.*/ simulator.UseJiggledBottomCells(); /* Run the simulation, by calling {{{Solve()}}}. */ simulator.Solve(); }
void TestPottsMonolayerWithDeath() throw (Exception) { EXIT_IF_PARALLEL; // Potts simulations don't work in parallel because they depend on NodesOnlyMesh for writing. // Create a simple 2D PottsMesh PottsMeshGenerator<2> generator(16, 4, 4, 24, 8, 2); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create cells std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_diff_type); // Create cell population PottsBasedCellPopulation<2> cell_population(*p_mesh, cells); // Set up cell-based simulation OnLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestPottsMonolayerWithDeath"); simulator.SetDt(0.1); simulator.SetEndTime(1.0); // Create update rules and pass to the simulation MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule); simulator.AddPottsUpdateRule(p_volume_constraint_update_rule); MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule); simulator.AddPottsUpdateRule(p_adhesion_update_rule); // Create cell killer and pass in to simulation c_vector<double,2> point = zero_vector<double>(2); point(1) = 16.0; c_vector<double,2> normal = zero_vector<double>(2); normal(1) = 1.0; MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, point, normal)); simulator.AddCellKiller(p_killer); // Run simulation simulator.Solve(); // Check the number of cells TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 18u); // Test no births or deaths TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u); TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 14u); }
// Testing Save void TestSave() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad"); simulator.SetEndTime(0.1); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); // Solve simulator.Solve(); // Save the results CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator); }
/* * The results may be visualized using {{{Visualize2dCentreCells}}} as described in the * previous test, with the results directory changed from {{{CellBasedDemo4}}} to {{{CellBasedDemo5}}}. * * == Test 6 - basic periodic mesh-based simulation with obstructions == * * We next show how to modify the previous test to include one * or more 'obstructions' within the domain. */ void TestMeshBasedMonolayerPeriodicSolidBottomBoundary() throw (Exception) { /* We make the same {{{Mesh}}}, {{{Cells}}}, {{{CellPopulation}}}, * {{{CellBasedSimulation}}} and forces as before, all we change is the output directory.*/ CylindricalHoneycombMeshGenerator generator(5, 2, 2); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; MAKE_PTR(StemCellProliferativeType, p_stem_type); CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_stem_type); MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices); cell_population.AddPopulationWriter<VoronoiDataWriter>(); OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("CellBasedDemo6"); //**Changed**// simulator.SetSamplingTimestepMultiple(50); simulator.SetEndTime(20.0); MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); simulator.AddForce(p_force); /* We now want to impose the condition y>0 on the cells. To do this we create a "shared pointer" to a {{{PlaneBoundaryCondition}}}. * Much like the {{{RandomCellKiller}}} earlier we pass arguments to the constructor (a point (0,0) on the plane (line in 2D) and an outward pointing normal to the plane (0,-1) ) using the {{{MAKE_PTR_ARGS}}} macro.*/ c_vector<double,2> point = zero_vector<double>(2); c_vector<double,2> normal = zero_vector<double>(2); normal(1) = -1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&cell_population, point, normal)); simulator.AddCellPopulationBoundaryCondition(p_bc); /* Finally we call the {{{Solve}}} method as in all other simulations.*/ simulator.Solve(); /* The next two lines are for test purposes only and are not part of this tutorial. */ TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 20u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10); }
/* * Cellular death has been tested in TestCaMonolayerWithDeath for one cell per lattice site. * This test is just to ensure that the above test works when there are multiple cells per lattice site. */ void TestMultipleCellsPerLatticeSiteWithDeath() throw (Exception) { EXIT_IF_PARALLEL; // Reset the maximum cell ID to zero (to account for previous tests) CellId::ResetMaxCellId(); // Create a simple 2D PottsMesh PottsMeshGenerator<2> generator(10, 0, 0, 10, 0, 0); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create cells std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, 2*p_mesh->GetNumNodes(), p_diff_type); // Specify where cells lie std::vector<unsigned> location_indices; for (unsigned index=0; index<p_mesh->GetNumNodes(); index++) { //adding two cells per lattice site location_indices.push_back(index); location_indices.push_back(index); } TS_ASSERT_EQUALS(location_indices.size(),2*p_mesh->GetNumNodes()); // Create cell population CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices, 2); // Set up cell-based simulation OnLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestMultipleCellsPerLatticeSiteWithDeath"); simulator.SetDt(0.1); simulator.SetEndTime(0.1); //only one step as only care about cells being killed // No movement rule, as we only care about cell death // Add a cell killer that will kill all cells in the top half of the domain c_vector<double,2> point = zero_vector<double>(2); point[1] = 4.5; c_vector<double,2> normal = unit_vector<double>(2,1); MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, point, normal)); // v>4.5 simulator.AddCellKiller(p_killer); // Run simulation simulator.Solve(); // Check the number of cells TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 100u); // Test no deaths and some births TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u); TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 100u); // Check cells above y=5.5 (i.e. above index 50) have been killed and removed. for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { if (i < 50) { TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetCellsUsingLocationIndex(i).size(), 2u); } else { TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetCellsUsingLocationIndex(i).size(), 0u); } } }
void TestCaBasedSquareMonolayer() { PottsMeshGenerator<2> generator(10, 0, 0, 10, 0, 0); PottsMesh<2>* p_mesh = generator.GetMesh(); // Scale so cells are on top of those in the above centre based tests p_mesh->Scale(1.0,sqrt(3.0)*0.5); // Specify where cells lie std::vector<unsigned> location_indices; for (unsigned i=0; i<100; i++) { location_indices.push_back(i); } std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_differentiated_type); CellsGenerator<UniformCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_differentiated_type); // Make cells with x<5.0 apoptotic (so no source term) boost::shared_ptr<AbstractCellProperty> p_apoptotic_property = cells[0]->rGetCellPropertyCollection().GetCellPropertyRegistry()->Get<ApoptoticCellProperty>(); for (unsigned i=0; i<cells.size(); i++) { c_vector<double,2> cell_location; cell_location = p_mesh->GetNode(i)->rGetLocation(); if (cell_location(0) < 5.0) { cells[i]->AddCellProperty(p_apoptotic_property); } // Set initial condition for PDE cells[i]->GetCellData()->SetItem("variable",1.0); } TS_ASSERT_EQUALS(p_apoptotic_property->GetCellCount(), 50u); CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices); // Set up simulation time for file output SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 10); // Create PDE and boundary condition objects MAKE_PTR_ARGS(AveragedSourceParabolicPde<2>, p_pde, (cell_population, 0.1, 1.0, -1.0)); MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0)); // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE ChastePoint<2> lower(-5.0, -5.0); ChastePoint<2> upper(15.0, 15.0); MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper)); // Create a PDE modifier and set the name of the dependent variable in the PDE MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid)); p_pde_modifier->SetDependentVariableName("variable"); // For coverage, output the solution gradient p_pde_modifier->SetOutputGradient(true); p_pde_modifier->SetupSolve(cell_population,"TestAveragedParabolicPdeWithNodeOnSquare"); // Run for 10 time steps for (unsigned i=0; i<10; i++) { SimulationTime::Instance()->IncrementTimeOneStep(); p_pde_modifier->UpdateAtEndOfTimeStep(cell_population); p_pde_modifier->UpdateAtEndOfOutputTimeStep(cell_population); } // Test the solution at some fixed points to compare with other cell populations CellPtr p_cell_0 = cell_population.GetCellUsingLocationIndex(0); TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[0], 0, 1e-4); TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[1], 0.0, 1e-4); TS_ASSERT_DELTA( p_cell_0->GetCellData()->GetItem("variable"), 0.8513, 2e-2); // Low tolerance as mesh is slightly larger than for off-lattice models // Checking it doesn't change for this cell population TS_ASSERT_DELTA(p_cell_0->GetCellData()->GetItem("variable"), 0.8343, 1e-4); }
void TestNodeBasedSquareMonolayer() { HoneycombMeshGenerator generator(10,10,0); MutableMesh<2,2>* p_generating_mesh = generator.GetMesh(); NodesOnlyMesh<2>* p_mesh = new NodesOnlyMesh<2>; p_mesh->ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_differentiated_type); CellsGenerator<UniformCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumNodes(), p_differentiated_type); // Make cells with x<5.0 apoptotic (so no source term) boost::shared_ptr<AbstractCellProperty> p_apoptotic_property = cells[0]->rGetCellPropertyCollection().GetCellPropertyRegistry()->Get<ApoptoticCellProperty>(); for (unsigned i=0; i<cells.size(); i++) { c_vector<double,2> cell_location; cell_location = p_mesh->GetNode(i)->rGetLocation(); if (cell_location(0) < 5.0) { cells[i]->AddCellProperty(p_apoptotic_property); } // Set initial condition for PDE cells[i]->GetCellData()->SetItem("variable",1.0); } TS_ASSERT_EQUALS(p_apoptotic_property->GetCellCount(), 50u); NodeBasedCellPopulation<2> cell_population(*p_mesh, cells); // Set up simulation time for file output SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 10); // Create PDE and boundary condition objects MAKE_PTR_ARGS(AveragedSourceParabolicPde<2>, p_pde, (cell_population, 0.1, 1.0, -1.0)); MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0)); // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE ChastePoint<2> lower(-5.0, -5.0); ChastePoint<2> upper(15.0, 15.0); MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper)); // Create a PDE modifier and set the name of the dependent variable in the PDE MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid)); p_pde_modifier->SetDependentVariableName("variable"); // For coverage, output the solution gradient p_pde_modifier->SetOutputGradient(true); p_pde_modifier->SetupSolve(cell_population,"TestAveragedParabolicPdeWithNodeOnSquare"); // Run for 10 time steps for (unsigned i=0; i<10; i++) { SimulationTime::Instance()->IncrementTimeOneStep(); p_pde_modifier->UpdateAtEndOfTimeStep(cell_population); p_pde_modifier->UpdateAtEndOfOutputTimeStep(cell_population); } // Test the solution at some fixed points to compare with other cell populations CellPtr p_cell_0 = cell_population.GetCellUsingLocationIndex(0); TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[0], 0, 1e-4); TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[1], 0.0, 1e-4); TS_ASSERT_DELTA( p_cell_0->GetCellData()->GetItem("variable"), 0.8513, 1e-4); // Clear memory delete p_mesh; }
void TestArchiveParabolicBoxDomainPdeModifier() { // Create a file for archiving OutputFileHandler handler("archive", false); handler.SetArchiveDirectory(); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "ParabolicBoxDomainPdeModifier.arch"; // Separate scope to write the archive { // Create PDE and boundary condition objects MAKE_PTR_ARGS(UniformSourceParabolicPde<2>, p_pde, (-0.1)); MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0)); // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE ChastePoint<2> lower(-10.0, -10.0); ChastePoint<2> upper(10.0, 10.0); MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper)); // Create a PDE modifier and set the name of the dependent variable in the PDE std::vector<double> data(10); for (unsigned i=0; i<10; i++) { data[i] = i + 0.45; } Vec vector = PetscTools::CreateVec(data); ParabolicBoxDomainPdeModifier<2> modifier(p_pde, p_bc, false, p_cuboid, 2.0, vector); modifier.SetDependentVariableName("averaged quantity"); // Create an output archive std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); // Serialize via pointer AbstractCellBasedSimulationModifier<2,2>* const p_modifier = &modifier; output_arch << p_modifier; } // Separate scope to read the archive { AbstractCellBasedSimulationModifier<2,2>* p_modifier2; // Restore the modifier std::ifstream ifs(archive_filename.c_str()); boost::archive::text_iarchive input_arch(ifs); input_arch >> p_modifier2; // Test that member variables are correct TS_ASSERT_EQUALS((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->rGetDependentVariableName(), "averaged quantity"); TS_ASSERT_DELTA((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->GetStepSize(), 2.0, 1e-5); TS_ASSERT_EQUALS((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->AreBcsSetOnBoxBoundary(), true); Vec solution = (static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->GetSolution(); ReplicatableVector solution_repl(solution); TS_ASSERT_EQUALS(solution_repl.GetSize(), 10u); for (unsigned i=0; i<10; i++) { TS_ASSERT_DELTA(solution_repl[i], i + 0.45, 1e-6); } delete p_modifier2; } }
/* * This test can be used to generate steady state crypts for use * as the starting points of other simulations. * * You need to specify : * the kind of cell-cycle model to use on line 64, * WntConcentration on line 69, * change any model parameters around line 90, * and give the simulator options around line 95. */ void TestGenerateSteadyStateCryptArchives() throw (Exception) { std::string output_directory = "SteadyStateCrypt"; double end_of_simulation = 150.0; // hours double time_of_each_run = 10.0; // for each run - the more saves and loads the better for testing this // Create mesh unsigned cells_across = 13; unsigned cells_up = 25; double crypt_width = 12.1; unsigned thickness_of_ghost_layer = 3; CylindricalHoneycombMeshGenerator generator(cells_across, cells_up,thickness_of_ghost_layer, crypt_width/cells_across); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); double crypt_length = cells_up*(sqrt(3.0)/2.0)*crypt_width/cells_across; // Get location indices corresponding to real cells std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(0.0); // Set up cells std::vector<CellPtr> cells; CryptCellsGenerator<StochasticWntCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, location_indices, true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices, false, 30.0); // Last parameter adjusts Ghost spring stiffness in line with the linear_force later on // Set cell population to output cell types crypt.AddCellPopulationCountWriter<CellMutationStatesCountWriter>(); WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetWntConcentrationParameter(1.0/3.0); WntConcentration<2>::Instance()->SetCellPopulation(crypt); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); CryptSimulation2d simulator(crypt); simulator.SetOutputDirectory(output_directory); // Set length of simulation here simulator.SetEndTime(time_of_each_run); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); simulator.AddForce(p_linear_force); MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length)); simulator.AddCellKiller(p_killer); // UNUSUAL SET UP HERE ///////////////////////////////////// p_linear_force->SetMeinekeSpringStiffness(30.0); //normally 15.0; // 0.3/30 = 0.01 (i.e. Meineke's values) simulator.UseJiggledBottomCells(); // END OF UNUSUAL SET UP! ////////////////////////////////// simulator.Solve(); CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator); /* * HOW_TO_TAG Cell Based/Simulation * Save and load ('checkpoint') a cell-based simulation to file. */ for (double t=time_of_each_run; t<end_of_simulation+0.5; t += time_of_each_run) { CryptSimulation2d* p_simulator = CellBasedSimulationArchiver<2, CryptSimulation2d>::Load("SteadyStateCrypt",t); p_simulator->SetEndTime(t+time_of_each_run); p_simulator->Solve(); CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(p_simulator); delete p_simulator; } SimulationTime::Destroy(); RandomNumberGenerator::Destroy(); WntConcentration<2>::Destroy(); }
void Test2DVertexCryptRepresentativeSimulationForProfiling() { // Set start time SimulationTime::Instance()->SetStartTime(0.0); // Create mesh unsigned crypt_width = 18; unsigned crypt_height = 25; CylindricalHoneycombVertexMeshGenerator generator(crypt_width, crypt_height, true); Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh(); // Make crypt shorter for sloughing double crypt_length = 20.0; // Create cells std::vector<CellPtr> cells; MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++) { SimpleWntCellCycleModel* p_model = new SimpleWntCellCycleModel; p_model->SetDimension(2); double birth_time = - RandomNumberGenerator::Instance()->ranf()* ( p_model->GetTransitCellG1Duration() + p_model->GetSG2MDuration() ); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_transit_type); p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } // Create cell population VertexBasedCellPopulation<2> crypt(*p_mesh, cells); // Set up Wnt gradient WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetCellPopulation(crypt); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); // Create crypt simulation from cell population and force law CryptSimulation2d simulator(crypt); simulator.SetSamplingTimestepMultiple(50); simulator.SetEndTime(30.0); simulator.SetOutputDirectory("Test2DVertexCryptRepresentativeSimulationForProfiling"); // Create a force law and pass it to the simulation MAKE_PTR(NagaiHondaForce<2>, p_nagai_honda_force); simulator.AddForce(p_nagai_honda_force); // ...and with that the target area modifier MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); // Add a cell killer MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length)); simulator.AddCellKiller(p_killer); // Run simulation simulator.Solve(); // Tidy up WntConcentration<2>::Destroy(); }
void TestMeshBasedCryptWithMutations() throw(Exception) { EXIT_IF_PARALLEL; double time_of_each_run = 10.0; double end_simulations = 600.0; CylindricalHoneycombMeshGenerator generator(10, 10, 2); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; CryptCellsGenerator<StochasticWntCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, location_indices, true); boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<ApcTwoHitCellMutationState>()); MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices); cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>(); cell_population.SetCellAncestorsToLocationIndices(); double crypt_height = 8.0; WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetCellPopulation(cell_population); WntConcentration<2>::Instance()->SetCryptLength(crypt_height); CryptSimulation2d simulator(cell_population); simulator.SetOutputDirectory("MeshBasedCryptWithMutations"); simulator.SetSamplingTimestepMultiple(100); simulator.SetEndTime(10); //modify at end of timestep MAKE_PTR(SimulationEndTimeModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); cell_population.AddCellWriter<CellAncestorWriter>(); MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); simulator.AddForce(p_linear_force); MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&cell_population, crypt_height)); simulator.AddCellKiller(p_killer); simulator.Solve(); for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { unsigned node_index = cell_population.GetLocationIndexUsingCell(*cell_iter); if (node_index == 132) // Chosen from looking at the results from steady state { cell_iter->SetMutationState(p_state); } } double normal_damping_constant = cell_population.GetDampingConstantNormal(); cell_population.SetDampingConstantMutant(10*normal_damping_constant); CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator); simulator.SetEndTime(20); for (double t = time_of_each_run; t<end_simulations+0.5; t += time_of_each_run) { CryptSimulation2d* p_simulator = CellBasedSimulationArchiver<2, CryptSimulation2d>::Load("MeshBasedCryptWithMutations",t); p_simulator->SetEndTime(t+time_of_each_run); p_simulator->Solve(); CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(p_simulator); delete p_simulator; } CellBasedEventHandler::Headings(); CellBasedEventHandler::Report(); WntConcentration<2>::Destroy(); }
/** * This test runs multiple crypt simulations and records whether * or not labelled cells are in a randomly chosen crypt section. */ void TestMultipleCryptSimulations() throw (Exception) { std::string output_directory = "MakeMoreMeinekeGraphs"; double crypt_length = 22.0; // Create mesh unsigned cells_across = 13; unsigned cells_up = 25; double crypt_width = 12.1; unsigned thickness_of_ghost_layer = 3; unsigned num_simulations = 2; // Guess of maximum number of cells a crypt section may contain unsigned max_length_of_crypt_section = 5 * (unsigned)sqrt(pow(cells_across/2.0+1,2.0) + pow((double)cells_up,2.0)); std::vector<unsigned> labelled_cells_counter(max_length_of_crypt_section); for (unsigned i=0; i<max_length_of_crypt_section; i++) { labelled_cells_counter[i] = 0; } double time_of_each_run; std::vector<bool> labelled; CryptStatistics* p_crypt_statistics; // Create cell population MeshBasedCellPopulationWithGhostNodes<2>* p_crypt; CylindricalHoneycombMeshGenerator generator(cells_across, cells_up, thickness_of_ghost_layer, crypt_width/cells_across); std::vector<unsigned> location_indices; Cylindrical2dMesh* p_mesh; SimulationTime* p_simulation_time; // Loop over the number of simulations for (unsigned simulation_index=0; simulation_index<num_simulations; simulation_index++) { // Create new structures for each simulation p_mesh = generator.GetCylindricalMesh(); location_indices = generator.GetCellLocationIndices(); // Reset start time SimulationTime::Destroy(); p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(0.0); // Set up cells std::vector<CellPtr> temp_cells; CryptCellsGenerator<StochasticDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(temp_cells, p_mesh, std::vector<unsigned>(), true, 0.3, 2.0, 3.0, 4.0, true); // This awkward way of setting up the cells is a result of #430 std::vector<CellPtr> cells; for (unsigned i=0; i<location_indices.size(); i++) { cells.push_back(temp_cells[location_indices[i]]); } // Set up crypt p_crypt = new MeshBasedCellPopulationWithGhostNodes<2>(*p_mesh, cells, location_indices); // Set cell population to output cell types p_crypt->AddPopulationWriter<CellMutationStatesCountWriter>(); // Set up crypt simulation CryptSimulation2d simulator(*p_crypt, false, false); simulator.SetOutputDirectory(output_directory); // Set length of simulation here time_of_each_run = 10.0*simulator.GetDt(); // for each run simulator.SetEndTime(time_of_each_run); // Create a force laws and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetMeinekeSpringStiffness(30.0); // normally 15.0; simulator.AddForce(p_linear_force); // Set up cell killer MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length)); simulator.AddCellKiller(p_killer); simulator.UseJiggledBottomCells(); // Set up crypt statistics p_crypt_statistics = new CryptStatistics(*p_crypt); // Run for a bit simulator.Solve(); p_crypt_statistics->LabelSPhaseCells(); simulator.SetEndTime(2.0*time_of_each_run); simulator.Solve(); std::vector<CellPtr> crypt_section = p_crypt_statistics->GetCryptSection(crypt_length + 2.0, 8.0, 8.0); labelled = p_crypt_statistics->AreCryptSectionCellsLabelled(crypt_section); // Store information from this simulation in a global vector for (unsigned cell_index=0; cell_index < labelled.size(); cell_index++) { TS_ASSERT(cell_index < labelled_cells_counter.size()); if (labelled[cell_index]) { labelled_cells_counter[cell_index]++; } } // Tidy up cells.clear(); labelled.clear(); WntConcentration<2>::Destroy(); delete p_crypt_statistics; delete p_crypt; } // Calculate percentage of labelled cells at each position in 'labelled_cells_counter' std::vector<double> percentage_of_labelled_cells(max_length_of_crypt_section); for (unsigned index=0; index < max_length_of_crypt_section; index ++) { percentage_of_labelled_cells[index] = (double) labelled_cells_counter[index]/num_simulations; } // Write data to file SimpleDataWriter writer1(output_directory, "percentage_of_labelled_cells.dat", percentage_of_labelled_cells, false); // Test against previous run // ... and checking visualization of labelled cells against previous run OutputFileHandler handler(output_directory, false); std::string results_file = handler.GetOutputDirectoryFullPath() + "percentage_of_labelled_cells.dat"; FileComparison( results_file, "crypt/test/data/MakeMoreMeinekeGraphs/percentage_of_labelled_cells.dat").CompareFiles(); RandomNumberGenerator::Destroy(); }
/* * === Testing the cell property === * * We begin by testing that our new cell property is implemented correctly. */ void TestMotileCellProperty() throw(Exception) { /* We begin by testing that some of the base class methods work correctly. * We typically use shared pointers to create and access a cell property * like {{{MotileCellProperty}}}, for which it makes sense for all cells * that have the same mutation to share a pointer to the same cell property * object (although strictly speaking, they are not required to). Observe that * in this case we have provided a value for the member variable {{{mColour}}} * in the {{{MotileCellProperty}}} constructor.*/ MAKE_PTR_ARGS(MotileCellProperty, p_property, (8)); /* Each cell property has a member variable, {{{mCellCount}}}, which * stores the number of cells with this cell property. We can test whether * {{{mCellCount}}} is being updated correctly by our cell property, as follows. */ TS_ASSERT_EQUALS(p_property->GetCellCount(), 0u); p_property->IncrementCellCount(); TS_ASSERT_EQUALS(p_property->GetCellCount(), 1u); p_property->DecrementCellCount(); TS_ASSERT_EQUALS(p_property->GetCellCount(), 0u); TS_ASSERT_THROWS_THIS(p_property->DecrementCellCount(), "Cannot decrement cell count: no cells have this cell property"); /* We can also test whether our cell property is of a given type, as follows. */ TS_ASSERT_EQUALS(p_property->IsType<WildTypeCellMutationState>(), false); TS_ASSERT_EQUALS(p_property->IsType<MotileCellProperty>(), true); /* We can also test that archiving is implemented correctly for our cell * property, as follows (further details on how to implement and * test archiving can be found at ChasteGuides/BoostSerialization). */ OutputFileHandler handler("archive", false); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "property.arch"; { AbstractCellProperty* const p_const_property = new MotileCellProperty(7); p_const_property->IncrementCellCount(); TS_ASSERT_EQUALS(p_const_property->GetCellCount(), 1u); TS_ASSERT_EQUALS(dynamic_cast<MotileCellProperty*>(p_const_property)->GetColour(), 7u); std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); output_arch << p_const_property; delete p_const_property; } { AbstractCellProperty* p_arch_property; std::ifstream ifs(archive_filename.c_str()); boost::archive::text_iarchive input_arch(ifs); input_arch >> p_arch_property; TS_ASSERT_EQUALS(p_arch_property->GetCellCount(), 1u); MotileCellProperty* p_real_property = dynamic_cast<MotileCellProperty*>(p_arch_property); TS_ASSERT(p_real_property != NULL); TS_ASSERT_EQUALS(p_real_property->GetColour(), 7u); delete p_arch_property; } }
/** * Create a simulation of a NodeBasedCellPopulation with a NodeBasedCellPopulationMechanicsSystem * and a CellKiller. Test that no exceptions are thrown, and write the results to file. */ void TestCellDeath() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath"); simulator.SetEndTime(0.5); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Add cell killer MAKE_PTR_ARGS(RandomCellKiller<2>, p_killer, (&node_based_cell_population, 0.997877574)); simulator.AddCellKiller(p_killer); // Solve simulator.Solve(); // Check some results TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u); TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 20u); std::vector<double> node_8_location = simulator.GetNodeLocation(8); TS_ASSERT_DELTA(node_8_location[0], 3.4729, 1e-4); TS_ASSERT_DELTA(node_8_location[1], 1.0051, 1e-4); std::vector<double> node_3_location = simulator.GetNodeLocation(3); TS_ASSERT_DELTA(node_3_location[0], 2.9895, 1e-4); TS_ASSERT_DELTA(node_3_location[1], 0.3105, 1e-4); // Test the results are written correctly FileFinder generated_type_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.vizcelltypes", RelativeTo::ChasteTestOutput); FileFinder generated_node_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.viznodes", RelativeTo::ChasteTestOutput); FileFinder reference_type_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.vizcelltypes",RelativeTo::ChasteSourceRoot); FileFinder reference_node_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.viznodes",RelativeTo::ChasteSourceRoot); FileComparison type_files(generated_type_file,reference_type_file); FileComparison node_files(generated_node_file,reference_node_file); }
/* * EMPTYLINE * * Note that you '''cannot view the results of a 3D simulation using the Java visualiser''' but * to visualize the results, use Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information. * * Load the file {{{/tmp/$USER/testoutput/NodeBasedSpheroid/results_from_time_0/results.pvd}}}, * and add spherical glyphs to represent cells. * * EMPTYLINE * * == Test 3 - a node-based simulation on a restricted geometry == * * EMPTYLINE * * In the third test we run a node-based simulation restricted to the surface of a sphere. */ void TestOnSurfaceOfSphere() { /** The next line is needed because we cannot currently run node based simulations in parallel. */ EXIT_IF_PARALLEL; /* * We begin with exactly the same code as the previous test: we create a cell population * from a mesh and vector of cells, and use this in turn to create * a simulation object. */ std::vector<Node<3>*> nodes; nodes.push_back(new Node<3>(0u, false, 0.5, 0.0, 0.0)); nodes.push_back(new Node<3>(1u, false, -0.5, 0.0, 0.0)); nodes.push_back(new Node<3>(2u, false, 0.0, 0.5, 0.0)); nodes.push_back(new Node<3>(3u, false, 0.0, -0.5, 0.0)); NodesOnlyMesh<3> mesh; /* To run node-based simulations you need to define a cut off length (second argument in * {{{ConstructNodesWithoutMesh}}}), which defines the connectivity of the nodes by defining * a radius of interaction. */ mesh.ConstructNodesWithoutMesh(nodes, 1.5); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<UniformCellCycleModel, 3> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); NodeBasedCellPopulation<3> cell_population(mesh, cells); OffLatticeSimulation<3> simulator(cell_population); simulator.SetOutputDirectory("NodeBasedOnSphere"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); /* As before, we create a linear spring force and pass it to the simulation object. */ MAKE_PTR(GeneralisedLinearSpringForce<3>, p_force); simulator.AddForce(p_force); /* * This time we create a {{{CellPopulationBoundaryCondition}}} and pass this to * the {{{OffLatticeSimulation}}}. Here we use a {{{SphereGeometryBoundaryCondition}}} * which restricts cells to lie on a sphere (in 3D) or circle (in 2D). * * For a list of possible boundary conditions see subclasses of {{{AbstractCellPopulationBoundaryCondition}}}. * These can be found in the inheritance diagram, here, [class:AbstractCellPopulationBoundaryCondition AbstractCellPopulationBoundaryCondition]. * Note that some of these boundary conditions are not compatible with node-based simulations see the specific class documentation for details, * if you try to use an incompatible class then you will receive a warning. * * First we set the centre (0,0,1) and radius of the sphere (1). */ c_vector<double,3> centre = zero_vector<double>(3); centre(2) = 1.0; double radius = 1.0; /* We then make a pointer to the boundary condition using the MAKE_PTR_ARGS macro, and pass * it to the {{{OffLatticeSimulation}}}. */ MAKE_PTR_ARGS(SphereGeometryBoundaryCondition<3>, p_boundary_condition, (&cell_population, centre, radius)); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition); /* To run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); /* The next two lines are for test purposes only and are not part of this tutorial. */ TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 8u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 10.0, 1e-10); /* To avoid memory leaks, we conclude by deleting any pointers that we created in the test.*/ for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
void TestArchivingOfCell() throw(Exception) { OutputFileHandler handler("archive", false); handler.SetArchiveDirectory(); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "cell.arch"; // Archive a cell { SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(2.0, 4); // Create mutation state boost::shared_ptr<AbstractCellProperty> p_healthy_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>()); boost::shared_ptr<AbstractCellProperty> p_type(CellPropertyRegistry::Instance()->Get<StemCellProliferativeType>()); // Create cell-cycle model FixedDurationGenerationBasedCellCycleModel* p_cell_model = new FixedDurationGenerationBasedCellCycleModel(); // Create SRN Goldbeter1991SrnModel* p_srn_model = new Goldbeter1991SrnModel(); // Create cell property collection CellPropertyCollection collection; MAKE_PTR(CellLabel, p_label); collection.AddProperty(p_label); // Create cell CellPtr p_cell(new Cell(p_healthy_state, p_cell_model, p_srn_model, false, collection)); p_cell->SetCellProliferativeType(p_type); p_cell->InitialiseCellCycleModel(); p_cell->InitialiseSrnModel(); p_simulation_time->IncrementTimeOneStep(); TS_ASSERT_EQUALS(p_cell->GetAge(), 0.5); TS_ASSERT_EQUALS(p_cell->GetAncestor(), UNSIGNED_UNSET); // Set ancestor MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (2u)); p_cell->SetAncestor(p_cell_ancestor); TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u); // Set CellVecData with some actual content boost::shared_ptr<AbstractCellProperty> p_vec_data(CellPropertyRegistry::Instance()->Get<CellVecData>()); p_cell->AddCellProperty(p_vec_data); Vec item_1 = PetscTools::CreateAndSetVec(2, -17.3); // <-17.3, -17.3> p_cell->GetCellVecData()->SetItem("item 1", item_1); // Check properties set correctly CellPropertyCollection& final_collection = p_cell->rGetCellPropertyCollection(); TS_ASSERT_EQUALS(final_collection.GetSize(), 7u); TS_ASSERT_EQUALS(final_collection.HasProperty<WildTypeCellMutationState>(), true); TS_ASSERT_EQUALS(final_collection.HasProperty<ApcOneHitCellMutationState>(), false); TS_ASSERT_EQUALS(final_collection.HasProperty<ApcTwoHitCellMutationState>(), false); TS_ASSERT_EQUALS(final_collection.HasProperty<CellLabel>(), true); TS_ASSERT_EQUALS(final_collection.HasPropertyType<AbstractCellProperty>(), true); TS_ASSERT_EQUALS(final_collection.HasPropertyType<AbstractCellMutationState>(), true); TS_ASSERT_EQUALS(final_collection.HasPropertyType<CellAncestor>(), true); TS_ASSERT_EQUALS(final_collection.HasPropertyType<CellId>(), true); TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u); for (CellPropertyCollection::Iterator it = final_collection.Begin(); it != final_collection.End(); ++it) { TS_ASSERT_EQUALS(final_collection.HasProperty(*it), true); bool is_wildtype = (*it)->IsType<WildTypeCellMutationState>(); bool is_label = (*it)->IsType<CellLabel>(); bool is_ancestor = (*it)->IsType<CellAncestor>(); bool is_cellid = (*it)->IsType<CellId>(); bool is_data = (*it)->IsType<CellData>(); bool is_vec_data = (*it)->IsType<CellVecData>(); bool is_stem = (*it)->IsType<StemCellProliferativeType>(); bool is_any_of_above = is_wildtype || is_label || is_ancestor || is_cellid || is_data || is_vec_data || is_stem; TS_ASSERT_EQUALS(is_any_of_above, true); } // Create another cell boost::shared_ptr<AbstractCellProperty> p_another_healthy_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>()); FixedDurationGenerationBasedCellCycleModel* p_another_cell_model = new FixedDurationGenerationBasedCellCycleModel(); Goldbeter1991SrnModel* p_another_srn_model = new Goldbeter1991SrnModel(); CellPtr p_another_cell(new Cell(p_another_healthy_state, p_another_cell_model, p_another_srn_model, false, collection)); boost::shared_ptr<AbstractCellProperty> p_another_vec_data(new CellVecData); p_another_cell->AddCellProperty(p_another_vec_data); TS_ASSERT_EQUALS(p_cell->GetCellVecData()->GetNumItems(), 1u); TS_ASSERT_EQUALS(p_another_cell->GetCellVecData()->GetNumItems(), 0u); Vec another_item_1 = PetscTools::CreateAndSetVec(2, 42.0); // <42, 42> p_another_cell->GetCellVecData()->SetItem("item 1", another_item_1); // Create an output archive std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); CellPtr const p_const_cell = p_cell; // Write the cell to the archive output_arch << static_cast<const SimulationTime&> (*p_simulation_time); output_arch << p_const_cell; // Write the second cell also CellPtr const p_another_const_cell = p_another_cell; output_arch << p_another_const_cell; // Tidy up SimulationTime::Destroy(); PetscTools::Destroy(item_1); PetscTools::Destroy(another_item_1); } // Restore CellPtr { // Need to set up time to initialize a cell SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(1.0); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(2.0, 1); // will be restored // Initialize a cell CellPtr p_cell; // Restore the cell std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); input_arch >> *p_simulation_time; input_arch >> p_cell; // Check the simulation time has been restored (through the cell) TS_ASSERT_EQUALS(p_simulation_time->GetTime(), 0.5); TS_ASSERT_EQUALS(p_simulation_time->GetTimeStep(), 0.5); TS_ASSERT_EQUALS(p_cell->GetAge(), 0.5); TS_ASSERT_EQUALS(static_cast<FixedDurationGenerationBasedCellCycleModel*>(p_cell->GetCellCycleModel())->GetGeneration(), 0u); TS_ASSERT(dynamic_cast<Goldbeter1991SrnModel*>(p_cell->GetSrnModel())); TS_ASSERT_EQUALS(p_cell->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true); AbstractCellCycleModel* p_cc_model = p_cell->GetCellCycleModel(); TS_ASSERT_EQUALS(p_cc_model->GetCell(), p_cell); AbstractSrnModel* p_srn_model = p_cell->GetSrnModel(); TS_ASSERT_EQUALS(p_srn_model->GetCell(), p_cell); CellPropertyCollection& collection = p_cell->rGetCellPropertyCollection(); TS_ASSERT_EQUALS(collection.GetSize(), 7u); TS_ASSERT_EQUALS(collection.HasProperty<WildTypeCellMutationState>(), true); TS_ASSERT_EQUALS(collection.HasProperty<ApcOneHitCellMutationState>(), false); TS_ASSERT_EQUALS(collection.HasProperty<ApcTwoHitCellMutationState>(), false); TS_ASSERT_EQUALS(collection.HasProperty<CellLabel>(), true); TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellProperty>(), true); TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellMutationState>(), true); TS_ASSERT_EQUALS(collection.HasPropertyType<CellAncestor>(), true); TS_ASSERT_EQUALS(collection.HasPropertyType<CellId>(), true); TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u); // Check explicitly for CellVecData as it is not available by default as CellData TS_ASSERT_EQUALS(collection.HasPropertyType<CellVecData>(), true); // Check that the Vec stored in CellVecData was unarchived correctly boost::shared_ptr<CellVecData> p_cell_vec_data = boost::static_pointer_cast<CellVecData>(collection.GetPropertiesType<CellVecData>().GetProperty()); PetscInt vec_size; VecGetSize(p_cell_vec_data->GetItem("item 1"), &vec_size); TS_ASSERT_EQUALS(vec_size, 2); ReplicatableVector rep_item_1(p_cell_vec_data->GetItem("item 1")); TS_ASSERT_DELTA(rep_item_1[0], -17.3, 2e-14); for (CellPropertyCollection::Iterator it = collection.Begin(); it != collection.End(); ++it) { TS_ASSERT_EQUALS(collection.HasProperty(*it), true); bool is_wildtype = (*it)->IsType<WildTypeCellMutationState>(); bool is_label = (*it)->IsType<CellLabel>(); bool is_ancestor = (*it)->IsType<CellAncestor>(); bool is_cellid = (*it)->IsType<CellId>(); bool is_data = (*it)->IsType<CellData>(); bool is_vec_data = (*it)->IsType<CellVecData>(); bool is_stem = (*it)->IsType<StemCellProliferativeType>(); bool is_any_of_above = is_wildtype || is_label || is_ancestor || is_cellid || is_data || is_vec_data || is_stem; TS_ASSERT_EQUALS(is_any_of_above, true); } // Try another cell CellPtr p_another_cell; input_arch >> p_another_cell; ReplicatableVector rep_another_item_1(p_another_cell->GetCellVecData()->GetItem("item 1")); TS_ASSERT_DELTA(rep_another_item_1[0], 42.0, 2e-14); } }
void TestStatechart() throw(Exception) { /** The next line is needed because we cannot currently run node based simulations in parallel. */ EXIT_IF_PARALLEL; //Specify distal arm dimensions double cylinderRadius=10; double cylinderLength=200; /* * CREATE CELL POPULATION * Seed a few cells at the end of a cylinder representing the distal gonad arm. */ std::vector<Node<3>*> nodes; for(double i=0; i<15; i+=5){ for(double j=0; j<12; j++){ double xcoord= cylinderLength+cylinderRadius-i; Node<3>* my_node; my_node=new Node<3>(12*(i/5)+j, false, xcoord, (cylinderRadius-5)*sin(2*3.14159*(j/12)), (cylinderRadius-5)*cos(2*3.14159*(j/12))); nodes.push_back(my_node); } } //MAKE CELL POPULATION NodesOnlyMesh<3>* p_mesh = new NodesOnlyMesh<3>; /* Define a cut off length for the connectivity of the nodes by setting a radius of interaction. */ p_mesh->ConstructNodesWithoutMesh(nodes, 30.0); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<StatechartCellCycleModel, 3> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumNodes(), p_transit_type); NodeBasedCellPopulation<3> cell_population(*p_mesh, cells); //loop through cells and initialise cell data properties that will be used in interfacing //with the statechart cell_population.SetUseVariableRadii(true); for (NodeBasedCellPopulation<3>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter){ Node<3>* cell_centre_node = cell_population.GetNode(cell_population.GetLocationIndexUsingCell(*cell_iter)); cell_centre_node->SetRadius(2.5); (*cell_iter)->GetCellData()->SetItem("Radius",2.5); (*cell_iter)->GetCellData()->SetItem("Proliferating",1.0); (*cell_iter)->GetCellData()->SetItem("DistanceAwayFromDTC",0.0); } cell_population.Update(); //SET SIMULATION PROPERTIES, ADD REPULSION FORCE OffLatticeSimulation<3> simulator(cell_population); simulator.SetOutputDirectory("StatechartsGeneratedTest"); simulator.SetSamplingTimestepMultiple(12); simulator.SetDt(1.0/300.0); simulator.SetEndTime(15.0); MAKE_PTR(RepulsionForce<3>, p_force1); simulator.AddForce(p_force1); //ADD CYLINDRICAL BOUNDARY CONDITION c_vector<double,3> left_end; left_end[0]=0; left_end[1]=0; left_end[2]=0; MAKE_PTR_ARGS(DistalArmBoundaryCondition<3>, p_boundary_condition, (&cell_population,left_end,cylinderLength,cylinderRadius,1e-5)); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition); //ADD A CELL KILLER ON FAR END //Plane based, corresponds to egg laying c_vector<double,3> pointOnKillerPlane=zero_vector<double>(3); c_vector<double,3> normalToKillerPlane=zero_vector<double>(3); pointOnKillerPlane[0]=0; pointOnKillerPlane[1]=0; normalToKillerPlane[0]=-1; MAKE_PTR_ARGS(PlaneBasedCellKiller<3>, cell_killer, (&cell_population, pointOnKillerPlane, normalToKillerPlane)); simulator.AddCellKiller(cell_killer); /* RUN */ simulator.Solve(); /* GARBAGE COLLECTION*/ for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } delete p_mesh; };
void TestMakeMeinekeGraphs() throw (Exception) { // Specify output directory std::string output_directory = "MakeMeinekeGraphs"; // Create mesh double crypt_length = 22.0; unsigned cells_across = 13; unsigned cells_up = 25; double crypt_width = 12.1; unsigned thickness_of_ghost_layer = 3; CylindricalHoneycombMeshGenerator generator(cells_across, cells_up, thickness_of_ghost_layer, crypt_width/cells_across); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); // Get location indices corresponding to real cells std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); // Set up cells std::vector<CellPtr> temp_cells; CryptCellsGenerator<StochasticDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(temp_cells, p_mesh, std::vector<unsigned>(), true, 0.3, 2.0, 3.0, 4.0, true); // This awkward way of setting up the cells is a result of #430 std::vector<CellPtr> cells; for (unsigned i=0; i<location_indices.size(); i++) { cells.push_back(temp_cells[location_indices[i]]); } // Create cell population MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices, false, 30.0); // Last parameter adjusts Ghost spring stiffness in line with the linear_force later on // Set cell population to output cell types crypt.AddPopulationWriter<CellMutationStatesCountWriter>(); // Create and configure simulation CryptSimulation2d simulator(crypt, false, false); simulator.SetOutputDirectory(output_directory); double time_of_each_run = simulator.GetDt(); // for each run simulator.SetEndTime(time_of_each_run); // Create a force law and cell killer and pass then to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetMeinekeSpringStiffness(30.0); // normally 15.0; simulator.AddForce(p_linear_force); MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length)); simulator.AddCellKiller(p_killer); // Specify unusual set up simulator.UseJiggledBottomCells(); // Test CryptStatistics::GetCryptSectionPeriodic() by labelling a column of cells... CryptStatistics crypt_statistics(crypt); std::vector<CellPtr> test_section = crypt_statistics.GetCryptSectionPeriodic(crypt_length + 2.0, 8.0, 8.0); for (unsigned i=0; i<test_section.size(); i++) { test_section[i]->AddCellProperty(crypt.GetCellPropertyRegistry()->Get<CellLabel>()); } simulator.Solve(); CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator); // ... and checking visualization of labelled cells against previous run OutputFileHandler handler(output_directory, false); std::string results_file = handler.GetOutputDirectoryFullPath() + "results_from_time_0/results.viznodes"; TS_ASSERT(NumericFileComparison( results_file, "crypt/test/data/MakeMeinekeGraphs/results.viznodes").CompareFiles()); std::string results_file2 = handler.GetOutputDirectoryFullPath() + "results_from_time_0/results.vizcelltypes"; FileComparison( results_file2, "crypt/test/data/MakeMeinekeGraphs/results.vizcelltypes").CompareFiles(); // Next, test LabelSPhaseCells() for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); cell_iter != crypt.End(); ++cell_iter) { cell_iter->RemoveCellProperty<CellLabel>(); } crypt_statistics.LabelSPhaseCells(); // Iterate over cells checking for correct labels unsigned counter = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); cell_iter != crypt.End(); ++cell_iter) { bool is_labelled = cell_iter->HasCellProperty<CellLabel>(); bool in_s_phase = (cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase() == S_PHASE); TS_ASSERT_EQUALS(is_labelled, in_s_phase); if (in_s_phase) { counter++; } } TS_ASSERT_EQUALS(counter, 28u); // Test that LabelAllCellsAsHealthy sets all cells back to be UNLABELLED wild type cells crypt_statistics.LabelAllCellsAsHealthy(); // Iterate over cells checking for correct labels counter = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); cell_iter != crypt.End(); ++cell_iter) { TS_ASSERT_EQUALS(cell_iter->GetMutationState()->IsType<WildTypeCellMutationState>(), true); TS_ASSERT_EQUALS(cell_iter->HasCellProperty<CellLabel>(), false); counter++; } TS_ASSERT_EQUALS(counter, simulator.rGetCellPopulation().GetNumRealCells()); crypt_statistics.LabelSPhaseCells(); simulator.SetEndTime(2*time_of_each_run); simulator.Solve(); // TEST CryptStatistics::AreCryptSectionCellsLabelled // Set cells which are not in the crypt section to be in state APC +/-, so that we can // see the section test_section = crypt_statistics.GetCryptSectionPeriodic(crypt_length + 2.0, 8.0, 8.0); MAKE_PTR(ApcOneHitCellMutationState, p_apc1); for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); cell_iter != crypt.End(); ++cell_iter) { bool in_section = false; for (unsigned vector_index=0; vector_index<test_section.size(); vector_index++) { if (test_section[vector_index] == *cell_iter) { in_section = true; } } if (!in_section) { cell_iter->SetMutationState(p_apc1); } } simulator.SetEndTime(3*time_of_each_run); simulator.Solve(); std::vector<CellPtr> crypt_section = crypt_statistics.GetCryptSection(crypt_length + 2.0, 8.0, 8.0); std::vector<bool> labelled = crypt_statistics.AreCryptSectionCellsLabelled(crypt_section); // Test that the vector of booleans corresponds with a visualisation of the data - // only the first few cells at the base of the crypt have been labelled for (unsigned vector_index=0; vector_index<labelled.size(); vector_index++) { if (vector_index == 2u || vector_index == 3u || vector_index == 4u) { TS_ASSERT_EQUALS(labelled[vector_index], true); } else { TS_ASSERT_EQUALS(labelled[vector_index], false); } } RandomNumberGenerator::Destroy(); }
/** * Test a cell-based simulation with a non-Meineke spring system. * * This test consists of a standard crypt projection model simulation with a * radial sloughing cell killer, a crypt projection cell-cycle model that * depends on a radial Wnt gradient, and the crypt projection model spring * system, and store the results for use in later archiving tests. */ void TestOffLatticeSimulationWithCryptProjectionSpringSystem() throw (Exception) { double a = 0.2; double b = 2.0; WntConcentration<2>::Instance()->SetCryptProjectionParameterA(a); WntConcentration<2>::Instance()->SetCryptProjectionParameterB(b); // Set up mesh int num_cells_depth = 20; int num_cells_width = 20; unsigned thickness_of_ghost_layer = 3; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, thickness_of_ghost_layer); MutableMesh<2,2>* p_mesh = generator.GetMesh(); double crypt_length = (double)num_cells_depth *sqrt(3.0)/2.0; std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); ChasteCuboid<2> bounding_box=p_mesh->CalculateBoundingBox(); double width_of_mesh = (num_cells_width/(num_cells_width+2.0*thickness_of_ghost_layer))*(bounding_box.GetWidth(0)); double height_of_mesh = (num_cells_depth/(num_cells_depth+2.0*thickness_of_ghost_layer))*(bounding_box.GetWidth(1)); p_mesh->Translate(-width_of_mesh/2, -height_of_mesh/2); // To start off with, set up all cells to have TransitCellProliferativeType std::vector<CellPtr> cells; MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); for (unsigned i=0; i<location_indices.size(); i++) { SimpleWntCellCycleModel* p_model = new SimpleWntCellCycleModel(); p_model->SetDimension(2); p_model->SetWntStemThreshold(0.95); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_transit_type); p_cell->InitialiseCellCycleModel(); double birth_time = - RandomNumberGenerator::Instance()->ranf()* ( p_model->GetTransitCellG1Duration() +p_model->GetSG2MDuration()); p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } // Make a cell population MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Set up the Wnt gradient WntConcentration<2>::Instance()->SetType(RADIAL); WntConcentration<2>::Instance()->SetCellPopulation(crypt); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); // Make a cell-based simulation OffLatticeSimulation<2> crypt_projection_simulator(crypt, false, false); // Create a force law and pass it to the simulation MAKE_PTR(CryptProjectionForce, p_force); crypt_projection_simulator.AddForce(p_force); // Create a radial cell killer and pass it in to the cell-based simulation c_vector<double,2> centre = zero_vector<double>(2); double crypt_radius = pow(crypt_length/a, 1.0/b); MAKE_PTR_ARGS(RadialSloughingCellKiller, p_killer, (&crypt, centre, crypt_radius)); crypt_projection_simulator.AddCellKiller(p_killer); // Set up the simulation crypt_projection_simulator.SetOutputDirectory("CryptProjectionSimulation"); crypt_projection_simulator.SetEndTime(0.25); // Run the simulation TS_ASSERT_THROWS_NOTHING(crypt_projection_simulator.Solve()); // These cells just divided and have been gradually moving apart. // This is happening around (4, -1). The exact spring length is slightly // compiler/architecture dependent. // These results are from time 0.25. std::vector<double> node_a_location = crypt_projection_simulator.GetNodeLocation(301); std::vector<double> node_b_location = crypt_projection_simulator.GetNodeLocation(504); c_vector<double, 2> distance_between; distance_between(0) = node_a_location[0] - node_b_location[0]; distance_between(1) = node_a_location[1] - node_b_location[1]; // Note that this distance varies based on the quality of the original honeycomb mesh, // the precision of the machine and the optimisation level TS_ASSERT_DELTA(norm_2(distance_between), 0.6516, 4.0e-3); // Test the Wnt concentration result WntConcentration<2>* p_wnt = WntConcentration<2>::Instance(); TS_ASSERT_DELTA(p_wnt->GetWntLevel(crypt.GetCellUsingLocationIndex(257)), 0.7781, 1e-3); TS_ASSERT_DELTA(p_wnt->GetWntLevel(crypt.GetCellUsingLocationIndex(503)), 0.9038, 1e-3); // Tidy up WntConcentration<2>::Destroy(); }
/* * Create and simulate a simple 3D cell population of about 1000 cells within a cuboid box with sloughing on the top edge */ void Test3dNodeBasedInBoxWithSloughing() { double size_of_box = 8.0; unsigned cells_across = 12; double scaling = size_of_box/(double(cells_across-1)); // Create a simple 3D NodeBasedCellPopulation consisting of cells evenly spaced in a regular grid std::vector<Node<3>*> nodes; unsigned index = 0; for (unsigned i=0; i<cells_across; i++) { for (unsigned j=0; j<cells_across; j++) { for (unsigned k=0; k<cells_across; k++) { nodes.push_back(new Node<3>(index, false, (double) i * scaling , (double) j * scaling, (double) k * scaling)); index++; } } } NodesOnlyMesh<3> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<UniformCellCycleModel, 3> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); NodeBasedCellPopulation<3> node_based_cell_population(mesh, cells); //node_based_cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>(); // Set up cell-based simulation OffLatticeSimulation<3> simulator(node_based_cell_population); simulator.SetOutputDirectory("Representative3dNodeBased"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); // Create a force law and pass it to the simulation MAKE_PTR(RepulsionForce<3>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some plane boundary conditions to restrict to box and pass them to the simulation // Restrict to x>0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_1, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,0))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_1); // Restrict to x < size_of_box MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_2, (&node_based_cell_population, size_of_box*unit_vector<double>(3,0), unit_vector<double>(3,0))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_2); // Restrict to y>0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_3, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,1))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_3); // Restrict to y < size_of_box MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_4, (&node_based_cell_population, size_of_box*unit_vector<double>(3,1), unit_vector<double>(3,1))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_4); // Restrict to z > 0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_5, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,2))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_5); // Create cell killer at z= size_of_box MAKE_PTR_ARGS(PlaneBasedCellKiller<3>, p_cell_killer,(&node_based_cell_population, size_of_box*unit_vector<double>(3,2), unit_vector<double>(3,2))); simulator.AddCellKiller(p_cell_killer); // Run simulation simulator.Solve(); // Check some results TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 1128u); AbstractCellPopulation<3>::Iterator cell_iter = simulator.rGetCellPopulation().Begin(); for (unsigned i=0; i<100; i++) { ++cell_iter; } c_vector<double,3> node_location = simulator.rGetCellPopulation().GetLocationOfCellCentre(*cell_iter); TS_ASSERT_DELTA(node_location[0],0.9604, 1e-4); TS_ASSERT_DELTA(node_location[1],8.0, 1e-4); TS_ASSERT_DELTA(node_location[2],3.6539, 1e-4); // Avoid memory leak for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }