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; }
void TestAddCellWithShovingBasedDivisionRuleAndShovingRequired() { /** * In this test of ShovingCaBasedDivisionRule we check the case where there is * no room to divide without the cells being shoved to the edge of the mesh. */ // Create a simple Potts mesh PottsMeshGenerator<2> generator(5, 0, 0, 5, 0, 0); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create 25 cells, one for each node std::vector<unsigned> location_indices; for (unsigned index=0; index<25; index++) { location_indices.push_back(index); } std::vector<CellPtr> cells; CellsGenerator<FixedG1GenerationalCellCycleModel, 1> cells_generator; cells_generator.GenerateBasic(cells, location_indices.size()); // Create cell population CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices); // Make a new cell to add MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); FixedG1GenerationalCellCycleModel* p_model = new FixedG1GenerationalCellCycleModel(); CellPtr p_new_cell(new Cell(p_state, p_model)); p_new_cell->SetCellProliferativeType(p_stem_type); p_new_cell->SetBirthTime(-1); // Set the division rule for our population to be the shoving division rule boost::shared_ptr<AbstractCaBasedDivisionRule<2> > p_division_rule_to_set(new ShovingCaBasedDivisionRule<2>()); cell_population.SetCaBasedDivisionRule(p_division_rule_to_set); // Get the division rule back from the population and try to add new cell by dividing cell at site 0; boost::shared_ptr<AbstractCaBasedDivisionRule<2> > p_division_rule = cell_population.GetCaBasedDivisionRule(); // Select central cell CellPtr p_cell_12 = cell_population.GetCellUsingLocationIndex(12); // Try to divide but cant as hit boundary TS_ASSERT_THROWS_THIS(p_division_rule->CalculateDaughterNodeIndex(p_new_cell, p_cell_12, cell_population), "Cells reaching the boundary of the domain. Make the Potts mesh larger."); }
void TestAddCell() throw(Exception) { // Create a simple 2D PottsMesh with one cell PottsMeshGenerator<2> generator(2, 1, 2, 2, 1, 2); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); // Create cell population PottsBasedCellPopulation<2> cell_population(*p_mesh, cells); // Test we have the correct number of cells and elements TS_ASSERT_EQUALS(cell_population.GetNumElements(), 1u); TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 1u); // Create a new cell MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_new_cell(new Cell(p_state, p_model)); p_new_cell->SetCellProliferativeType(p_stem_type); // Add new cell to the cell population by dividing the cell AbstractCellPopulation<2>::Iterator cell_iter_1 = cell_population.Begin(); cell_population.AddCell(p_new_cell, zero_vector<double>(2), *cell_iter_1); TS_ASSERT_EQUALS(cell_population.GetLocationIndexUsingCell(p_new_cell), 1u); TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 2u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 2u); // Check locations of parent and daughter cell AbstractCellPopulation<2>::Iterator cell_iter_2 = cell_population.Begin(); TS_ASSERT_EQUALS(cell_population.GetLocationIndexUsingCell(*cell_iter_2), 0u); ++cell_iter_2; TS_ASSERT_EQUALS(cell_population.GetLocationIndexUsingCell(*cell_iter_2), 1u); // Check Elements are as expected TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(0)->GetNodeGlobalIndex(0), 0u); TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(0)->GetNodeGlobalIndex(1), 1u); TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(1)->GetNodeGlobalIndex(0), 2u); TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(1)->GetNodeGlobalIndex(1), 3u); }
void TestAddCellWithShovingBasedDivisionRule() { /** * In this test we create a new ShovingCaBasedDivisionRule, divide a cell with it * and check that the new cells are in the correct locations. First, we test where * there is space around the cells. This is the default setup. */ // Create a simple Potts mesh PottsMeshGenerator<2> generator(5, 0, 0, 5, 0, 0); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create 9 cells in the central nodes std::vector<unsigned> location_indices; for (unsigned row=1; row<4; row++) { location_indices.push_back(1+row*5); location_indices.push_back(2+row*5); location_indices.push_back(3+row*5); } std::vector<CellPtr> cells; CellsGenerator<FixedG1GenerationalCellCycleModel, 1> cells_generator; cells_generator.GenerateBasic(cells, location_indices.size()); // Create cell population CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices); // Check the cell locations unsigned cell_locations[9] = {6, 7, 8, 11, 12, 13, 16, 17, 18}; unsigned index = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_EQUALS(cell_population.GetLocationIndexUsingCell(*cell_iter),cell_locations[index]) ++index; } // Make a new cell to add MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); FixedG1GenerationalCellCycleModel* p_model = new FixedG1GenerationalCellCycleModel(); CellPtr p_new_cell(new Cell(p_state, p_model)); p_new_cell->SetCellProliferativeType(p_stem_type); p_new_cell->SetBirthTime(-1); // Set the division rule for our population to be the shoving division rule boost::shared_ptr<AbstractCaBasedDivisionRule<2> > p_division_rule_to_set(new ShovingCaBasedDivisionRule<2>()); cell_population.SetCaBasedDivisionRule(p_division_rule_to_set); // Get the division rule back from the population and try to add new cell by dividing cell at site 0 boost::shared_ptr<AbstractCaBasedDivisionRule<2> > p_division_rule = cell_population.GetCaBasedDivisionRule(); // Select central cell CellPtr p_cell_12 = cell_population.GetCellUsingLocationIndex(12); // The ShovingCaBasedDivisionRule method IsRoomToDivide() always returns true TS_ASSERT_EQUALS((p_division_rule->IsRoomToDivide(p_cell_12, cell_population)), true); /* * Test adding the new cell to the population; this calls CalculateDaughterNodeIndex(). * The new cell moves into node 13. */ cell_population.AddCell(p_new_cell, p_cell_12); // Now check the cells are in the correct place TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 10u); // Note the cell originally on node 13 has been shoved to node 14 and the new cell is on node 13 unsigned new_cell_locations[10] = {6, 7, 8, 11, 12, 14, 16, 17, 18, 13}; index = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_EQUALS(cell_population.GetLocationIndexUsingCell(*cell_iter), new_cell_locations[index]) ++index; } }
void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::DivideLongSprings(double springDivisionThreshold) { // Only implemented for 2D elements assert(ELEMENT_DIM==2); std::vector<c_vector<unsigned, 5> > new_nodes; new_nodes = rGetMesh().SplitLongEdges(springDivisionThreshold); // Add new cells onto new nodes for (unsigned index=0; index<new_nodes.size(); index++) { // Copy the cell attached to one of the neighbouring nodes onto the new node unsigned new_node_index = new_nodes[index][0]; unsigned node_a_index = new_nodes[index][1]; unsigned node_b_index = new_nodes[index][2]; CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(node_a_index); // Create copy of cell property collection to modify for daughter cell CellPropertyCollection daughter_property_collection = p_neighbour_cell->rGetCellPropertyCollection(); // Remove the CellId from the daughter cell a new one will be assigned in the constructor daughter_property_collection.RemoveProperty<CellId>(); CellPtr p_new_cell(new Cell(p_neighbour_cell->GetMutationState(), p_neighbour_cell->GetCellCycleModel()->CreateCellCycleModel(), p_neighbour_cell->GetSrnModel()->CreateSrnModel(), false, daughter_property_collection)); // Add new cell to cell population this->mCells.push_back(p_new_cell); this->AddCellUsingLocationIndex(new_node_index,p_new_cell); // Update rest lengths // Remove old node pair // note node_a_index < node_b_index std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(node_a_index, node_b_index); double old_rest_length = mSpringRestLengths[node_pair]; std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair); mSpringRestLengths.erase(iter); // Add new pairs node_pair = this->CreateOrderedPair(node_a_index, new_node_index); mSpringRestLengths[node_pair] = 0.5*old_rest_length; node_pair = this->CreateOrderedPair(node_b_index, new_node_index); mSpringRestLengths[node_pair] = 0.5*old_rest_length; // If necessary add other new spring rest lengths for (unsigned pair_index=3; pair_index<5; pair_index++) { unsigned other_node_index = new_nodes[index][pair_index]; if (other_node_index != UNSIGNED_UNSET) { node_pair = this->CreateOrderedPair(other_node_index, new_node_index); double new_rest_length = rGetMesh().GetDistanceBetweenNodes(new_node_index, other_node_index); mSpringRestLengths[node_pair] = new_rest_length; } } } }
void TestAddAndRemoveAndAddWithOutUpdate() { EXIT_IF_PARALLEL; // This test doesn't work in parallel. SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(10.0, 1); // Create a simple mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements"); TetrahedralMesh<2,2> generating_mesh; generating_mesh.ConstructFromMeshReader(mesh_reader); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(generating_mesh, 1.2); // Create vector of cell location indices std::vector<unsigned> cell_location_indices; for (unsigned i=10; i<mesh.GetNumNodes(); i++) { if (i != 80) { cell_location_indices.push_back(i); } } // Set up cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, cell_location_indices.size()); cells[27]->StartApoptosis(); // Create a cell population, with some random particles NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, cell_location_indices); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u); TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 70u); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_new_cell(new Cell(p_state, p_model)); p_new_cell->SetCellProliferativeType(p_stem_type); p_new_cell->SetBirthTime(0); c_vector<double,2> new_location = zero_vector<double>(2); new_location[0] = 0.3433453454443; new_location[0] = 0.3435346344234; cell_population.AddCell(p_new_cell, new_location, cell_population.rGetCells().front() /*random choice of parent*/); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 82u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 71u); p_simulation_time->IncrementTimeOneStep(); unsigned num_removed = cell_population.RemoveDeadCells(); TS_ASSERT_EQUALS(num_removed, 1u); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 70u); FixedDurationGenerationBasedCellCycleModel* p_model2 = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_new_cell2(new Cell(p_state, p_model2)); p_new_cell2->SetCellProliferativeType(p_stem_type); p_new_cell2->SetBirthTime(0); c_vector<double,2> new_location2 = zero_vector<double>(2); new_location2[0] = 0.6433453454443; new_location2[0] = 0.6435346344234; cell_population.AddCell(p_new_cell2, new_location2, cell_population.rGetCells().front() /*random choice of parent*/); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 82u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 71u); }