/* * == Using the SRN model in a cell-based simulation == * * We conclude with a brief test demonstrating how {{{MySrnModel}}} can be used * in a cell-based simulation. */ void TestOffLatticeSimulationWithMySrnModel() throw(Exception) { /* We use the honeycomb vertex mesh generator to create a vertex mesh. */ HoneycombVertexMeshGenerator generator(2, 2); MutableVertexMesh<2,2>* p_mesh = generator.GetMesh(); /* Next, we create some cells. First, define the cells vector. */ std::vector<CellPtr> cells; /* We must create a shared_ptr to a {{{CellMutationState}}} with which to bestow the cells. * We make use of the macro MAKE_PTR to do this: the first argument is the class and * the second argument is the name of the shared_ptr. */ MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); /* Then we loop over the nodes. */ for (unsigned i=0; i<p_mesh->GetNumElements(); i++) { /* For each node we create a cell with our SRN model and simple Stochastic cell cycle model. */ StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel(); MySrnModel* p_srn_model = new MySrnModel; /* We choose to initialise the concentrations to random levels in each cell. */ std::vector<double> initial_conditions; initial_conditions.push_back(1.0-2.0*RandomNumberGenerator::Instance()->ranf()); initial_conditions.push_back(1.0-2.0*RandomNumberGenerator::Instance()->ranf()); p_srn_model->SetInitialConditions(initial_conditions); CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model)); p_cell->SetCellProliferativeType(p_stem_type); /* Now, we define a random birth time, chosen from [-T,0], where * T = t,,1,, + t,,2,,, where t,,1,, is a parameter representing the G,,1,, duration * of a stem cell, and t,,2,, is the basic S+G,,2,,+M phases duration. */ double birth_time = - RandomNumberGenerator::Instance()->ranf() * (p_cell_cycle_model->GetStemCellG1Duration() + p_cell_cycle_model->GetSG2MDuration()); /* We then set the birth time and push the cell back into the vector of cells. */ p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } /* Now that we have defined the mesh and cells, we can define the cell population, forces, areas modifier, and simulation * in the same way as the other tutorials. */ VertexBasedCellPopulation<2> cell_population(*p_mesh, cells); OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithMySrnModel"); simulator.SetEndTime(10.0); simulator.SetSamplingTimestepMultiple(50); MAKE_PTR(NagaiHondaForce<2>, p_force); simulator.AddForce(p_force); MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); /* Finally to run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); }
void CellsGenerator<CELL_CYCLE_MODEL,DIM>::GenerateGivenLocationIndices(std::vector<CellPtr>& rCells, const std::vector<unsigned> locationIndices, boost::shared_ptr<AbstractCellProperty> pCellProliferativeType) { assert(!locationIndices.empty()); unsigned num_cells = locationIndices.size(); rCells.clear(); rCells.reserve(num_cells); CellPropertyRegistry::Instance()->Clear(); for (unsigned i=0; i<num_cells; i++) { CELL_CYCLE_MODEL* p_cell_cycle_model = new CELL_CYCLE_MODEL; p_cell_cycle_model->SetDimension(DIM); boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>()); CellPtr p_cell(new Cell(p_state, p_cell_cycle_model)); if (!pCellProliferativeType) { p_cell->SetCellProliferativeType(CellPropertyRegistry::Instance()->Get<StemCellProliferativeType>()); } else { p_cell->SetCellProliferativeType(pCellProliferativeType); } double birth_time = 0.0 - locationIndices[i]; p_cell->SetBirthTime(birth_time); rCells.push_back(p_cell); } }
void TestArchiveTysonNovakCellCycleModels() { // Set up OutputFileHandler handler("archive", false); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "TysonNovakCellCycleModel.arch"; { // We must set up SimulationTime to avoid memory leaks SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1); // As usual, we archive via a pointer to the most abstract class possible AbstractCellCycleModel* const p_model = new TysonNovakCellCycleModel; p_model->SetDimension(3); p_model->SetBirthTime(-1.5); static_cast<TysonNovakCellCycleModel*>(p_model)->SetDt(0.085); // We must create a cell to be able to initialise the cell cycle model's ODE system MAKE_PTR(WildTypeCellMutationState, p_healthy_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); CellPtr p_cell(new Cell(p_healthy_state, p_model)); p_cell->SetCellProliferativeType(p_stem_type); p_cell->InitialiseCellCycleModel(); std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); output_arch << p_model; // Note that here, deletion of the cell-cycle model is handled by the cell destructor SimulationTime::Destroy(); } { // We must set SimulationTime::mStartTime here to avoid tripping an assertion SimulationTime::Instance()->SetStartTime(0.0); AbstractCellCycleModel* p_model2; std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); input_arch >> p_model2; TS_ASSERT_EQUALS(p_model2->GetDimension(), 3u); TS_ASSERT_DELTA(p_model2->GetBirthTime(), -1.5, 1e-12); TS_ASSERT_DELTA(static_cast<TysonNovakCellCycleModel*>(p_model2)->GetDt(), 0.085, 1e-3); TysonNovakCellCycleModel* p_static_cast_model = static_cast<TysonNovakCellCycleModel*>(p_model2); TysonNovak2001OdeSystem* p_ode_system = static_cast<TysonNovak2001OdeSystem*>(p_static_cast_model->GetOdeSystem()); TS_ASSERT(p_ode_system != NULL); // Avoid memory leaks delete p_model2; } }
void TestVertexCryptBoundaryForceMethods() throw (Exception) { // Create a simple 2D VertexMesh HoneycombVertexMeshGenerator generator(5, 5, false, 0.1, 0.5); MutableVertexMesh<2,2>* p_mesh = generator.GetMesh(); // Translate mesh so that some points are below y=0 p_mesh->Translate(0.0, -3.0); // Set up cells, one for each VertexElement. Give each cell // a birth time of -elem_index, so its age is elem_index std::vector<CellPtr> cells; boost::shared_ptr<AbstractCellMutationState> p_state(new WildTypeCellMutationState); boost::shared_ptr<AbstractCellProliferativeType> p_diff_type(new DifferentiatedCellProliferativeType); for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++) { FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_diff_type); double birth_time = 0.0 - elem_index; p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } // Create cell population VertexBasedCellPopulation<2> cell_population(*p_mesh, cells); // Create a force system VertexCryptBoundaryForce<2> force(100); for (unsigned i=0; i<cell_population.GetNumNodes(); i++) { cell_population.GetNode(i)->ClearAppliedForce(); } force.AddForceContribution(cell_population); // Check forces are correct for (unsigned i=0; i<cell_population.GetNumNodes(); i++) { TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[0], 0.0, 1e-4); double y = cell_population.GetNode(i)->rGetLocation()[1]; if (y >= 0.0) { // If y > 0, the force contribution should be zero... TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[1], 0.0, 1e-4); } else { // ...otherwise, the force contribution should be quadratic in y double expected_force = force.GetForceStrength()*y*y; TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[1], expected_force, 1e-4); } } }
void Test2DMonolayerRepresentativeSimulationForProfiling() throw (Exception) { // Set start time SimulationTime::Instance()->SetStartTime(0.0); // Create a simple mesh HoneycombMeshGenerator generator(5, 5, 0); MutableMesh<2,2>* p_mesh = generator.GetCircularMesh(3.5); // Create cells std::vector<CellPtr> cells; MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); for (unsigned i=0; i<p_mesh->GetNumNodes(); i++) { StochasticDurationGenerationBasedCellCycleModel* p_model = new StochasticDurationGenerationBasedCellCycleModel(); p_model->SetMaxTransitGenerations(UINT_MAX); p_model->SetTransitCellG1Duration(1.0); p_model->SetStemCellG1Duration(1.0); double birth_time = -RandomNumberGenerator::Instance()->ranf()* ( p_model->GetStemCellG1Duration() + 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 a cell population MeshBasedCellPopulation<2> cell_population(*p_mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("Test2DMonolayerRepresentativeSimulationForProfiling"); simulator.SetEndTime(50.0); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); p_force->SetCutOffLength(1.5); simulator.AddForce(p_force); // Run simulation simulator.Solve(); // Tidy up SimulationTime::Destroy(); RandomNumberGenerator::Destroy(); }
void CellsGenerator<CELL_CYCLE_MODEL,DIM>::GenerateBasic(std::vector<CellPtr>& rCells, unsigned numCells, const std::vector<unsigned> locationIndices, boost::shared_ptr<AbstractCellProperty> pCellProliferativeType) { rCells.clear(); if (!locationIndices.empty()) { // If location indices is given, then it needs to match the number of output cells if (numCells != locationIndices.size()) { EXCEPTION("The size of the locationIndices vector must match the required number of output cells"); } } rCells.reserve(numCells); // Create cells for (unsigned i=0; i<numCells; i++) { CELL_CYCLE_MODEL* p_cell_cycle_model = new CELL_CYCLE_MODEL; p_cell_cycle_model->SetDimension(DIM); boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>()); CellPtr p_cell(new Cell(p_state, p_cell_cycle_model)); if (!pCellProliferativeType) { p_cell->SetCellProliferativeType(CellPropertyRegistry::Instance()->Get<StemCellProliferativeType>()); } else { p_cell->SetCellProliferativeType(pCellProliferativeType); } double birth_time; if (!locationIndices.empty()) { birth_time = 0.0 - locationIndices[i]; } else { birth_time = 0.0 - i; } p_cell->SetBirthTime(birth_time); rCells.push_back(p_cell); } }
void TestGetCellUsingLocationIndexWithHaloCell() throw (Exception) { boost::shared_ptr<Node<3> > p_node(new Node<3>(10, false, 0.0, 0.0, 0.0)); // Create a cell. MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); mpNodeBasedCellPopulation->AddHaloCell(p_cell, p_node); TS_ASSERT_THROWS_NOTHING(mpNodeBasedCellPopulation->GetCellUsingLocationIndex(10)); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->GetCellUsingLocationIndex(10), p_cell); }
void TestNonPhaseBasedCcmException() throw (Exception) { // First set up SimulationTime (this is usually handled by a simulation object) SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1); // Create a cell mutation state MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_type); // Create a cell-cycle model UniformlyDistributedCellCycleModel* p_model = new UniformlyDistributedCellCycleModel(); // Create a cell CellPtr p_cell(new Cell(p_state, p_model)); // Create a SimpleTargetAreaModifier MAKE_PTR(SimpleTargetAreaModifier<2>, p_modifier); // Test that the correct exception is thrown if we try to call UpdateTargetAreas() on the population TS_ASSERT_THROWS_THIS(p_modifier->UpdateTargetAreaOfCell(p_cell), "SimpleTargetAreaModifier is to be used with a AbstractPhaseBasedCellCycleModel only"); CellBasedEventHandler::Reset(); // Otherwise logging has been started but not stopped due to exception above. }
void CellsGenerator<CELL_CYCLE_MODEL,DIM>::GenerateBasicRandom(std::vector<CellPtr>& rCells, unsigned numCells, boost::shared_ptr<AbstractCellProperty> pCellProliferativeType) { rCells.clear(); rCells.reserve(numCells); // Create cells for (unsigned i=0; i<numCells; i++) { CELL_CYCLE_MODEL* p_cell_cycle_model = new CELL_CYCLE_MODEL; p_cell_cycle_model->SetDimension(DIM); boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>()); CellPtr p_cell(new Cell(p_state, p_cell_cycle_model)); if (!pCellProliferativeType) { p_cell->SetCellProliferativeType(CellPropertyRegistry::Instance()->Get<StemCellProliferativeType>()); } else { p_cell->SetCellProliferativeType(pCellProliferativeType); } double birth_time = -p_cell_cycle_model->GetAverageStemCellCycleTime()*RandomNumberGenerator::Instance()->ranf(); if (p_cell->GetCellProliferativeType()->IsType<TransitCellProliferativeType>()) { birth_time = -p_cell_cycle_model->GetAverageTransitCellCycleTime()*RandomNumberGenerator::Instance()->ranf(); } p_cell->SetBirthTime(birth_time); rCells.push_back(p_cell); } }
void TestNodeBasedSimulationWithContactInhibition() { EXIT_IF_PARALLEL; // HoneycombMeshGenerator does not work in parallel // Create a simple 2D NodeBasedCellPopulation HoneycombMeshGenerator generator(5, 5, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel(); p_cycle_model->SetDimension(2); p_cycle_model->SetBirthTime(-10.0); p_cycle_model->SetQuiescentVolumeFraction(0.9); p_cycle_model->SetEquilibriumVolume(0.7854); //pi *(0.5)^2 p_cycle_model->SetStemCellG1Duration(0.1); p_cycle_model->SetTransitCellG1Duration(0.1); CellPtr p_cell(new Cell(p_state, p_cycle_model)); p_cell->SetCellProliferativeType(p_transit_type); cells.push_back(p_cell); } NodeBasedCellPopulation<2> cell_population(mesh, cells); cell_population.AddPopulationWriter<CellMutationStatesCountWriter>(); cell_population.AddCellWriter<CellVolumesWriter>(); cell_population.AddPopulationWriter<NodeVelocityWriter>(); // Create a simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestNodeBasedSimulationWithVolumeTracked"); TS_ASSERT_EQUALS(simulator.GetDt(), 1.0/120.0); // Default value for off-lattice simulations simulator.SetEndTime(simulator.GetDt()/2.0); // Create a volume-tracking modifier and pass it to the simulation MAKE_PTR(VolumeTrackingModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); p_force->SetCutOffLength(1.5); simulator.AddForce(p_force); // Run simulation simulator.Solve(); // Test that the node velocities file exists OutputFileHandler output_file_handler("TestNodeBasedSimulationWithVolumeTracked", false); FileFinder generated = output_file_handler.FindFile("results_from_time_0/nodevelocities.dat"); TS_ASSERT(generated.Exists()); // Test that the volumes of the cells are correct in CellData at the first timestep for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4); } simulator.SetEndTime(2.0); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the end time for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4); } // Check that the correct number of cells are labelled (i.e. experiencing contact inhibition) TS_ASSERT_EQUALS(cell_population.GetCellPropertyRegistry()->Get<CellLabel>()->GetCellCount(), 2u); }
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 TestTargetAreaOfDaughterCells() { // Plan: initialise a cell and have it divide at a fixed time. If cell divides at t, check that: // target area of mother cell at t - dt = mature target area // target area of daughter cells at t = half of that // target area of daughter cells at t + dt = half of mature target area + little increment // Create a simple 2D MutableVertexMesh with only one cell HoneycombVertexMeshGenerator generator(1, 1); MutableVertexMesh<2,2>* p_mesh = generator.GetMesh(); // Set up cell std::vector<CellPtr> cells; MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_transit_type); double birth_time = -11.0; // The cell cycle duration is 12 p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); // Create cell population VertexBasedCellPopulation<2> cell_population(*p_mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestTargetAreaOfDaughterCells"); simulator.SetEndTime(0.997); // Create a force law and pass it to the simulation MAKE_PTR(NagaiHondaForce<2>, p_nagai_honda_force); simulator.AddForce(p_nagai_honda_force); // Create a SimpleTargetAreaModifier MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); // Run simulation simulator.Solve(); // We should only have one cell now unsigned num_cells_before_division = simulator.rGetCellPopulation().GetNumRealCells(); TS_ASSERT_EQUALS(num_cells_before_division, 1u); // This is the cell from before; let's see what its target area is double target_area_before_division = p_cell->GetCellData()->GetItem("target area"); TS_ASSERT_DELTA(target_area_before_division,1.0,1e-9); // We now adjust the end time and run the simulation a bit further simulator.SetEndTime(1.001); simulator.Solve(); // We should now have two cells unsigned num_cells_at_division = simulator.rGetCellPopulation().GetNumRealCells(); TS_ASSERT_EQUALS(num_cells_at_division, 2u); // Iterate over the cells, checking their target areas for (VertexBasedCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double target_area_at_division = cell_iter->GetCellData()->GetItem("target area"); TS_ASSERT_DELTA(target_area_at_division,0.5,1e-9); } // We now do the same thing again simulator.SetEndTime(1.003); simulator.Solve(); // We should still have two cells unsigned num_cells_after_division = simulator.rGetCellPopulation().GetNumRealCells(); TS_ASSERT_EQUALS(num_cells_after_division, 2u); for (VertexBasedCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double target_area_after_division = cell_iter->GetCellData()->GetItem("target area"); // line to verify: cell_target_area *= 0.5*(1 + cell_age/g1_duration) double supposed_target_area_after_division = 0.5*(1+0.002/2.); TS_ASSERT_DELTA(target_area_after_division,supposed_target_area_after_division,1e-9); } }
void TestCryptProjectionForceMethods() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenerator doesnt work in parallel. // Create a mesh unsigned num_cells_width = 10; unsigned num_cells_depth = 10; unsigned thickness_of_ghost_layer = 0; SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0,1); HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, thickness_of_ghost_layer); MutableMesh<2,2>* p_mesh = generator.GetMesh(); // Centre the mesh at (0,0) 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); // Create some cells std::vector<CellPtr> cells; boost::shared_ptr<AbstractCellMutationState> p_state(new WildTypeCellMutationState); boost::shared_ptr<AbstractCellProperty> p_stem_type(new StemCellProliferativeType); for (unsigned i=0; i<p_mesh->GetNumNodes(); i++) { FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); if (i==4 || i==5) { p_cell->SetBirthTime(-0.5); } else { p_cell->SetBirthTime(-10.0); } p_cell->SetCellProliferativeType(p_stem_type); cells.push_back(p_cell); } // Create a cell population MeshBasedCellPopulation<2> cell_population(*p_mesh, cells); std::pair<CellPtr,CellPtr> cell_pair_4_5 = cell_population.CreateCellPair(cell_population.GetCellUsingLocationIndex(4), cell_population.GetCellUsingLocationIndex(5)); cell_population.MarkSpring(cell_pair_4_5); // Create a spring system with crypt surface z = 2*r WntConcentration<2>::Instance()->SetCryptProjectionParameterA(2.0); WntConcentration<2>::Instance()->SetCryptProjectionParameterB(1.0); CryptProjectionForce crypt_projection_force; // Test get methods TS_ASSERT_DELTA(crypt_projection_force.GetA(), 2.0, 1e-12); TS_ASSERT_DELTA(crypt_projection_force.GetB(), 1.0, 1e-12); // Test crypt height and gradient calculations c_vector<double, 2> node_location_2d = p_mesh->GetNode(0)->rGetLocation(); TS_ASSERT_DELTA(crypt_projection_force.CalculateCryptSurfaceHeightAtPoint(node_location_2d), 2.0*pow(norm_2(node_location_2d),1.0), 1e-12); TS_ASSERT_DELTA(crypt_projection_force.CalculateCryptSurfaceDerivativeAtPoint(node_location_2d), 2.0, 1e-12); // Test updating of mNode3dLocationMap crypt_projection_force.UpdateNode3dLocationMap(cell_population); // Move a node slightly ChastePoint<2> new_point; new_point.rGetLocation()[0] = node_location_2d[0]+0.05; new_point.rGetLocation()[1] = node_location_2d[1]; p_mesh->SetNode(0, new_point, false); // Test UpdateNode3dLocationMap() c_vector<double, 2> new_node_location_2d; new_node_location_2d[0] = new_point.rGetLocation()[0]; new_node_location_2d[1] = new_point.rGetLocation()[1]; crypt_projection_force.UpdateNode3dLocationMap(cell_population); // Check the map updates correctly (note that we have used no ghost nodes, so the map does contain 0) c_vector<double, 3> calculated_new_node_location_3d = crypt_projection_force.mNode3dLocationMap[0]; c_vector<double, 3> correct_new_node_location_3d; correct_new_node_location_3d[0] = new_node_location_2d[0]; correct_new_node_location_3d[1] = new_node_location_2d[1]; correct_new_node_location_3d[2] = crypt_projection_force.CalculateCryptSurfaceHeightAtPoint(new_node_location_2d); TS_ASSERT_DELTA(calculated_new_node_location_3d[0], correct_new_node_location_3d[0], 1e-12); TS_ASSERT_DELTA(calculated_new_node_location_3d[1], correct_new_node_location_3d[1], 1e-12); TS_ASSERT_DELTA(calculated_new_node_location_3d[2], correct_new_node_location_3d[2], 1e-12); // Test force calculation on a normal spring c_vector<double,2> force_on_spring; // between nodes 0 and 1 // Find one of the elements that nodes 0 and 1 live on ChastePoint<2> new_point2; new_point2.rGetLocation()[0] = new_point[0] + 0.01; new_point2.rGetLocation()[1] = new_point[1] + 0.01; unsigned elem_index = p_mesh->GetContainingElementIndex(new_point2, false); Element<2,2>* p_element = p_mesh->GetElement(elem_index); force_on_spring = crypt_projection_force.CalculateForceBetweenNodes(p_element->GetNodeGlobalIndex(1), p_element->GetNodeGlobalIndex(0), cell_population); TS_ASSERT_DELTA(force_on_spring[0], -5.7594, 1e-4); TS_ASSERT_DELTA(force_on_spring[1], 0.0230, 1e-4); // Test force calculation with a cutoff double dist = norm_2(p_mesh->GetVectorFromAtoB(p_element->GetNode(0)->rGetLocation(), p_element->GetNode(1)->rGetLocation())); crypt_projection_force.SetCutOffLength(dist - 0.1); force_on_spring = crypt_projection_force.CalculateForceBetweenNodes(p_element->GetNodeGlobalIndex(1), p_element->GetNodeGlobalIndex(0), cell_population); TS_ASSERT_DELTA(force_on_spring[0], 0.0, 1e-4); TS_ASSERT_DELTA(force_on_spring[1], 0.0, 1e-4); // Test force calculation for a pair of newly born neighbouring cells force_on_spring = crypt_projection_force.CalculateForceBetweenNodes(4, 5, cell_population); TS_ASSERT_DELTA(force_on_spring[0], 0.0, 1e-4); TS_ASSERT_DELTA(force_on_spring[1], 0.0, 1e-4); cell_population.UnmarkSpring(cell_pair_4_5); // For coverage, test force calculation for a pair of neighbouring apoptotic cells cell_population.GetCellUsingLocationIndex(6)->StartApoptosis(); cell_population.GetCellUsingLocationIndex(7)->StartApoptosis(); force_on_spring = crypt_projection_force.CalculateForceBetweenNodes(6, 7, cell_population); TS_ASSERT_DELTA(force_on_spring[0], 0.0, 1e-4); TS_ASSERT_DELTA(force_on_spring[1], 0.0, 1e-4); // Test force calculation for a particular node for (unsigned i=0; i<cell_population.GetNumNodes(); i++) { cell_population.GetNode(i)->ClearAppliedForce(); } crypt_projection_force.AddForceContribution(cell_population); TS_ASSERT_DELTA(cell_population.GetNode(0)->rGetAppliedForce()[0], 0.0, 1e-4); TS_ASSERT_DELTA(cell_population.GetNode(0)->rGetAppliedForce()[1], 0.0, 1e-4); // Test that in the case of a flat crypt surface (mA=mB=0), the results are the same as for Meineke2001SpringSystem WntConcentration<2>::Instance()->SetCryptProjectionParameterA(0.001); WntConcentration<2>::Instance()->SetCryptProjectionParameterB(0.001); CryptProjectionForce flat_crypt_projection_force; GeneralisedLinearSpringForce<2> linear_force; // Normally this would be set up at the start of rCalculateforcesOfEachNode flat_crypt_projection_force.UpdateNode3dLocationMap(cell_population); for (MeshBasedCellPopulation<2>::SpringIterator spring_iterator = cell_population.SpringsBegin(); spring_iterator != cell_population.SpringsEnd(); ++spring_iterator) { unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex(); unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex(); c_vector<double, 2> force_flat = flat_crypt_projection_force.CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, cell_population); c_vector<double, 2> force_meineke = linear_force.CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, cell_population); TS_ASSERT_DELTA(force_flat[0], force_meineke[0], 1e-3); TS_ASSERT_DELTA(force_flat[1], force_meineke[1], 1e-3); } WntConcentration<2>::Destroy(); }
void TestTysonNovakCellCycleModel() throw(Exception) { // Set up SimulationTime* p_simulation_time = SimulationTime::Instance(); unsigned num_timesteps = 50; p_simulation_time->SetEndTimeAndNumberOfTimeSteps(3.0, num_timesteps); double standard_divide_time = 75.19/60.0; // Test TysonNovakCellCycleModel methods for a healthy cell TysonNovakCellCycleModel* p_cell_model = new TysonNovakCellCycleModel; p_cell_model->SetBirthTime(p_simulation_time->GetTime()); TS_ASSERT_EQUALS(p_cell_model->CanCellTerminallyDifferentiate(), false); MAKE_PTR(WildTypeCellMutationState, p_healthy_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); CellPtr p_cell(new Cell(p_healthy_state, p_cell_model)); p_cell->SetCellProliferativeType(p_stem_type); p_cell->InitialiseCellCycleModel(); p_cell_model->SetDt(0.1/60.0); /* * For coverage, we create another cell-cycle model that is identical except that we * manually pass in an ODE solver. In this case, our ODE solver (BackwardEulerIvpOdeSolver) * is the same type as the solver used by the cell-cycle model if no solver is provided * (unless CVODE is used), so our results should be identical. */ boost::shared_ptr<CellCycleModelOdeSolver<TysonNovakCellCycleModel, BackwardEulerIvpOdeSolver> > p_solver(CellCycleModelOdeSolver<TysonNovakCellCycleModel, BackwardEulerIvpOdeSolver>::Instance()); p_solver->SetSizeOfOdeSystem(6); p_solver->Initialise(); TysonNovakCellCycleModel* p_other_cell_model = new TysonNovakCellCycleModel(p_solver); p_other_cell_model->SetBirthTime(p_simulation_time->GetTime()); // Timestep for non-adaptive solvers defaults to 0.0001 TS_ASSERT_EQUALS(p_other_cell_model->GetDt(), 0.0001); p_other_cell_model->SetDt(0.1/60.0); CellPtr p_other_cell(new Cell(p_healthy_state, p_other_cell_model)); p_other_cell->SetCellProliferativeType(p_stem_type); p_other_cell->InitialiseCellCycleModel(); // Test the cell is ready to divide at the right time for (unsigned i=0; i<num_timesteps/2; i++) { p_simulation_time->IncrementTimeOneStep(); double time = p_simulation_time->GetTime(); bool result = p_cell_model->ReadyToDivide(); bool other_result = p_other_cell_model->ReadyToDivide(); if (time > standard_divide_time) { TS_ASSERT_EQUALS(result, true); TS_ASSERT_EQUALS(other_result, true); } else { TS_ASSERT_EQUALS(result, false); TS_ASSERT_EQUALS(other_result, false); } } // Test ODE solution std::vector<double> proteins = p_cell_model->GetProteinConcentrations(); TS_ASSERT_EQUALS(proteins.size(), 6u); TS_ASSERT_DELTA(proteins[0], 0.10000000000000, 1e-2); TS_ASSERT_DELTA(proteins[1], 0.98913684535843, 1e-2); TS_ASSERT_DELTA(proteins[2], 1.54216806705641, 1e-1); TS_ASSERT_DELTA(proteins[3], 1.40562614481544, 2e-2); TS_ASSERT_DELTA(proteins[4], 0.67083371879876, 1e-2); TS_ASSERT_DELTA(proteins[5], 0.95328206604519, 2e-2); std::vector<double> other_proteins = p_other_cell_model->GetProteinConcentrations(); TS_ASSERT_EQUALS(other_proteins.size(), 6u); TS_ASSERT_DELTA(other_proteins[0], 0.10000000000000, 1e-2); TS_ASSERT_DELTA(other_proteins[1], 0.98913684535843, 1e-2); TS_ASSERT_DELTA(other_proteins[2], 1.54216806705641, 1e-1); TS_ASSERT_DELTA(other_proteins[3], 1.40562614481544, 2e-2); TS_ASSERT_DELTA(other_proteins[4], 0.67083371879876, 1e-2); TS_ASSERT_DELTA(other_proteins[5], 0.95328206604519, 2e-2); TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),true); // For coverage, we also test TysonNovakCellCycleModel methods for a mutant cell p_cell_model->ResetForDivision(); TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),false); TysonNovakCellCycleModel* p_cell_model2 = static_cast<TysonNovakCellCycleModel*> (p_cell_model->CreateCellCycleModel()); MAKE_PTR(ApcOneHitCellMutationState, p_mutation); CellPtr p_stem_cell_2(new Cell(p_mutation, p_cell_model2)); TS_ASSERT_EQUALS(p_cell_model2->ReadyToDivide(),false); p_stem_cell_2->SetCellProliferativeType(p_stem_type); TS_ASSERT_EQUALS(p_cell_model->ReadyToDivide(),false); TS_ASSERT_EQUALS(p_cell_model2->ReadyToDivide(),false); // Test the cell is ready to divide at the right time for (unsigned i=0; i<num_timesteps/2; i++) { p_simulation_time->IncrementTimeOneStep(); double time = p_simulation_time->GetTime(); bool result = p_cell_model->ReadyToDivide(); bool result2 = p_cell_model2->ReadyToDivide(); if (time > 2.0* standard_divide_time) { TS_ASSERT_EQUALS(result, true); TS_ASSERT_EQUALS(result2, true); } else { TS_ASSERT_EQUALS(result, false); TS_ASSERT_EQUALS(result2, false); } } // Test ODE solution proteins = p_cell_model->GetProteinConcentrations(); TS_ASSERT_EQUALS(proteins.size(), 6u); TS_ASSERT_DELTA(proteins[0], 0.10000000000000, 1e-2); TS_ASSERT_DELTA(proteins[1], 0.98913684535843, 1e-2); TS_ASSERT_DELTA(proteins[2], 1.54216806705641, 1e-1); TS_ASSERT_DELTA(proteins[3], 1.40562614481544, 1e-1); TS_ASSERT_DELTA(proteins[4], 0.67083371879876, 1e-2); TS_ASSERT_DELTA(proteins[5], 0.9662, 1e-2); // Coverage of AbstractOdeBasedCellCycleModel::SetProteinConcentrationsForTestsOnly() std::vector<double> test_results(6); for (unsigned i=0; i<6; i++) { test_results[i] = (double)i; } p_cell_model->SetProteinConcentrationsForTestsOnly(1.0, test_results); proteins = p_cell_model->GetProteinConcentrations(); for (unsigned i=0; i<6; i++) { TS_ASSERT_DELTA(proteins[i], test_results[i], 1e-6); } }
void RunTest(const std::string& rOutputDirName, const std::string& rModelName, const std::vector<std::string>& rArgs, bool testLookupTables=false, double tableTestV=-1000) { // Copy CellML file (and .out if present) into output dir OutputFileHandler handler(rOutputDirName, true); FileFinder cellml_file("heart/test/data/cellml/" + rModelName + ".cellml", RelativeTo::ChasteSourceRoot); handler.CopyFileTo(cellml_file); FileFinder out_file("heart/test/data/cellml/" + rModelName + ".out", RelativeTo::ChasteSourceRoot); if (out_file.Exists()) { handler.CopyFileTo(out_file); } // Create options file std::vector<std::string> args(rArgs); // args.push_back("--profile"); CellMLToSharedLibraryConverter converter(true); if (!args.empty()) { converter.CreateOptionsFile(handler, rModelName, args); } // Do the conversion FileFinder copied_file(rOutputDirName + "/" + rModelName + ".cellml", RelativeTo::ChasteTestOutput); DynamicCellModelLoaderPtr p_loader = converter.Convert(copied_file); // Apply a stimulus of -40 uA/cm^2 - should work for all models boost::shared_ptr<AbstractCardiacCellInterface> p_cell(CreateCellWithStandardStimulus(*p_loader, -40.0)); // Check that the default stimulus units are correct if (p_cell->HasCellMLDefaultStimulus()) { // Record the existing stimulus and re-apply it at the end boost::shared_ptr<AbstractStimulusFunction> original_stim = p_cell->GetStimulusFunction(); // Tell the cell to use the default stimulus and retrieve it boost::shared_ptr<RegularStimulus> p_reg_stim = p_cell->UseCellMLDefaultStimulus(); if (rModelName!="aslanidi_model_2009") // Even before recent changes aslanidi model has stimulus of -400 ! { // Stimulus magnitude should be approximately between -5 and -81 uA/cm^2 TS_ASSERT_LESS_THAN(p_reg_stim->GetMagnitude(),-5); TS_ASSERT_LESS_THAN(-81,p_reg_stim->GetMagnitude()); } // Stimulus duration should be approximately between 0.1 and 5 ms. TS_ASSERT_LESS_THAN(p_reg_stim->GetDuration(),6.01); TS_ASSERT_LESS_THAN(0.1,p_reg_stim->GetDuration()); // Stimulus period should be approximately between 70 (for bondarenko - seems fast! - would expect 8-10 beats per second for mouse) and 2000ms. TS_ASSERT_LESS_THAN(p_reg_stim->GetPeriod(),2000); TS_ASSERT_LESS_THAN(70,p_reg_stim->GetPeriod()); p_cell->SetIntracellularStimulusFunction(original_stim); } // Check lookup tables exist if they should if (testLookupTables && rModelName != "hodgkin_huxley_squid_axon_model_1952_modified") { double v = p_cell->GetVoltage(); p_cell->SetVoltage(tableTestV); TS_ASSERT_THROWS_CONTAINS(p_cell->GetIIonic(), "outside lookup table range"); p_cell->SetVoltage(v); } Simulate(rOutputDirName, rModelName, p_cell); }
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 TestVolumeTrackedOffLatticeSimulationArchiving() throw (Exception) { EXIT_IF_PARALLEL; // Create a simple 2D MeshBasedCellPopulation HoneycombMeshGenerator generator(2, 2, 0); MutableMesh<2,2>* p_mesh = generator.GetMesh(); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); std::vector<CellPtr> cells; for (unsigned i=0; i<p_mesh->GetNumNodes(); i++) { ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel(); p_cycle_model->SetDimension(2); p_cycle_model->SetBirthTime(-1.0); p_cycle_model->SetQuiescentVolumeFraction(0.7); p_cycle_model->SetEquilibriumVolume(1.0); p_cycle_model->SetStemCellG1Duration(0.1); p_cycle_model->SetTransitCellG1Duration(0.1); CellPtr p_cell(new Cell(p_state, p_cycle_model)); p_cell->SetCellProliferativeType(p_stem_type); p_cell->InitialiseCellCycleModel(); cells.push_back(p_cell); } MeshBasedCellPopulation<2> cell_population(*p_mesh, cells); // Create a contact inhibition simulator OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestVolumeTrackedOffLatticeSimulationSaveAndLoad"); double end_time = 0.01; simulator.SetEndTime(end_time); // Create a volume-tracking modifier and pass it to the simulation MAKE_PTR(VolumeTrackingModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); p_force->SetCutOffLength(1.5); simulator.AddForce(p_force); // Run simulation simulator.Solve(); CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator); TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 4u); TS_ASSERT_EQUALS((static_cast<MeshBasedCellPopulation<2>*>(&(simulator.rGetCellPopulation())))->GetNumRealCells(), 4u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 0.01, 1e-9); CellPtr p_cell = simulator.rGetCellPopulation().GetCellUsingLocationIndex(3); TS_ASSERT_DELTA(p_cell->GetAge(), 1.01, 1e-4); SimulationTime::Destroy(); SimulationTime::Instance()->SetStartTime(0.0); // Load simulation OffLatticeSimulation<2>* p_simulator = CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Load("TestVolumeTrackedOffLatticeSimulationSaveAndLoad", end_time); p_simulator->SetEndTime(0.2); TS_ASSERT_EQUALS(p_simulator->rGetCellPopulation().GetNumRealCells(), 4u); TS_ASSERT_EQUALS((static_cast<MeshBasedCellPopulation<2>*>(&(p_simulator->rGetCellPopulation())))->GetNumRealCells(), 4u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 0.01, 1e-9); CellPtr p_cell2 = p_simulator->rGetCellPopulation().GetCellUsingLocationIndex(3); TS_ASSERT_DELTA(p_cell2->GetAge(), 1.01, 1e-4); // Run simulation p_simulator->Solve(); // Tidy up delete p_simulator; // Test Warnings TS_ASSERT_EQUALS(Warnings::Instance()->GetNumWarnings(), 2u); Warnings::QuietDestroy(); }
void TestVertexBasedSimulationWithContactInhibition() { EXIT_IF_PARALLEL; // Output in cell-based simulations doesn't work in parallel ///\todo #2356 // Create a simple 2D VertexBasedCellPopulation HoneycombVertexMeshGenerator generator(2, 2); MutableVertexMesh<2,2>* p_mesh = generator.GetMesh(); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); std::vector<CellPtr> cells; for (unsigned i=0; i<p_mesh->GetNumElements(); i++) { ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel(); p_cycle_model->SetDimension(2); p_cycle_model->SetBirthTime(-10.0); p_cycle_model->SetQuiescentVolumeFraction(0.99); // Very high as cells are not that compressed, as low in number and want to check that contact inhibition works. p_cycle_model->SetEquilibriumVolume(1.0); // Target volume in NagaiHonda force p_cycle_model->SetStemCellG1Duration(0.1); p_cycle_model->SetTransitCellG1Duration(0.1); CellPtr p_cell(new Cell(p_state, p_cycle_model)); p_cell->SetCellProliferativeType(p_transit_type); cells.push_back(p_cell); } VertexBasedCellPopulation<2> cell_population(*p_mesh, cells); cell_population.AddPopulationWriter<CellMutationStatesCountWriter>(); cell_population.AddCellWriter<CellVolumesWriter>(); // Create a simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestVertexBasedSimulationWithVolumeTracked"); simulator.SetEndTime(simulator.GetDt()/2.0); // Create a volume-tracking modifier and pass it to the simulation MAKE_PTR(VolumeTrackingModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); // Create a force law and pass it to the simulation MAKE_PTR(NagaiHondaForce<2>, p_nagai_honda_force); simulator.AddForce(p_nagai_honda_force); // A NagaiHondaForce has to be used together with an AbstractTargetAreaModifier #2488 MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier); simulator.AddSimulationModifier(p_growth_modifier); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the first timestep for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), (*cell_iter)->GetCellData()->GetItem("volume"), 1e-4); } simulator.SetEndTime(2.0); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the end time for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), (*cell_iter)->GetCellData()->GetItem("volume"), 1e-4); } // Check that the correct number of cells are labelled (i.e. experiencing contact inhibition) TS_ASSERT_EQUALS(cell_population.GetCellPropertyRegistry()->Get<CellLabel>()->GetCellCount(),8u); }
void TestMeshBasedSimulationWithGhostNodesAndContactInhibition() { EXIT_IF_PARALLEL; // HoneycombMeshGenerator does not work in parallel. // Create a simple 2D MeshBasedCellPopulationWithGhostNodes HoneycombMeshGenerator generator(3, 3, 3); MutableMesh<2,2>* p_mesh = generator.GetMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); std::vector<CellPtr> cells; for (unsigned i=0; i<location_indices.size(); i++) { ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel(); p_cycle_model->SetDimension(2); p_cycle_model->SetBirthTime(-10.0); p_cycle_model->SetQuiescentVolumeFraction(0.9); p_cycle_model->SetEquilibriumVolume(0.866); //sqrt(3.0)/2 p_cycle_model->SetStemCellG1Duration(0.1); p_cycle_model->SetTransitCellG1Duration(0.1); CellPtr p_cell(new Cell(p_state, p_cycle_model)); p_cell->SetCellProliferativeType(p_transit_type); cells.push_back(p_cell); } MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells,location_indices); cell_population.AddPopulationWriter<CellMutationStatesCountWriter>(); cell_population.AddCellWriter<CellVolumesWriter>(); // Create a simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestMeshBasedSimulationWithGhostNodesAndVolumeTracked"); simulator.SetEndTime(simulator.GetDt()/2.0); // Create a volume-tracking modifier and pass it to the simulation MAKE_PTR(VolumeTrackingModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); p_force->SetCutOffLength(1.5); simulator.AddForce(p_force); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the first timestep for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), (*cell_iter)->GetCellData()->GetItem("volume"), 1e-4); } simulator.SetEndTime(2.0); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the end time for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), (*cell_iter)->GetCellData()->GetItem("volume"), 1e-4); } // Check that the correct number of cells are labelled (i.e. experiencing contact inhibition) TS_ASSERT_EQUALS(cell_population.GetCellPropertyRegistry()->Get<CellLabel>()->GetCellCount(), 12u); }
void TestOffLatticeSimulationWithMotileCellPropertyAndWriters() throw(Exception) { /* * We begin by creating a {{{NodeBasedCellPopulation}}}, just as in [wiki:UserTutorials/CreatingAndUsingANewCellProperty]. * We add the {{{MotileCellProperty}}} to a random selection of cells. * We also add the {{{CellLabel}}} to these cells so that we can easily visualize the different cell types. */ EXIT_IF_PARALLEL; HoneycombMeshGenerator generator(10, 10); MutableMesh<2,2>* p_generating_mesh = generator.GetCircularMesh(5); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); MAKE_PTR(MotileCellProperty, p_motile); MAKE_PTR(CellLabel, p_label); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPropertyCollection collection; if (RandomNumberGenerator::Instance()->ranf() < 0.2) { collection.AddProperty(p_motile); collection.AddProperty(p_label); } CellPtr p_cell(new Cell(p_state, p_model, false, collection)); p_cell->SetCellProliferativeType(p_diff_type); double birth_time = - RandomNumberGenerator::Instance()->ranf() * (p_model->GetStemCellG1Duration() + p_model->GetSG2MDuration()); p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } NodeBasedCellPopulation<2> cell_population(mesh, cells); /* In order to write cell motility data using our writer, we must add it to the list of writers * used by the population. This is achieved using the {{{AddCellWriter()}}} method, * which is templated. */ cell_population.AddCellWriter<CellMotilityWriter>(); /* We then pass in the cell population into an {{{OffLatticeSimulation}}}, * and set the output directory, output multiple, and end time. */ OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithMotileCellPropertyAndWriters"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); /* Next we create a force law and pass it to the {{{OffLatticeSimulation}}}, and call {{{Solve()}}} to run the simulation. */ MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); simulator.Solve(); }
/* * == Testing the SRN model == * * We begin by testing that our new cell-cycle model is implemented correctly. */ void TestMySrnModel() throw(Exception) { /* Test that we can construct a {{{MySrnModel}}} object: */ TS_ASSERT_THROWS_NOTHING(MySrnModel srn_model); /* Now we construct and initialise a cell with a {{{MySrnModel}}}.*/ MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel(); MySrnModel* p_srn_model = new MySrnModel; CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model)); p_cell->SetCellProliferativeType(p_diff_type); p_cell->InitialiseCellCycleModel(); p_cell->InitialiseSrnModel(); /* Now increment time and check the ODE in {{{MySrnModel}}} is solved correctly. */ double end_time = 10; unsigned num_steps = 1000; SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(end_time, num_steps); for (unsigned i=0; i<num_steps; i++) { SimulationTime::Instance()->IncrementTimeOneStep(); double current_time = SimulationTime::Instance()->GetTime(); /* Check that the ODE system is solved correctly */ p_srn_model->SimulateToCurrentTime(); // Test converged to steady state TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); } /* Lastly, we briefly test that archiving of {{{MySrnModel}}} has * been implemented correctly. Create an {{{OutputFileHandler}}} and use * this to define a filename for the archive. */ OutputFileHandler handler("archive", false); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "my_srn_model.arch"; /* Create an output archive. */ { /* Destroy the current instance of {{{SimulationTime}}} and create another instance. * Set the start time, end time and number of time steps. */ SimulationTime::Destroy(); SimulationTime::Instance()->SetStartTime(0.0); SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(3.0, 4); /* Create a cell with associated srn and cell-cycle model. */ StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel(); AbstractSrnModel* p_srn_model = new MySrnModel; CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model)); p_cell->SetCellProliferativeType(p_diff_type); p_cell->InitialiseCellCycleModel(); p_cell->InitialiseSrnModel(); /* Move forward two time steps. */ p_simulation_time->IncrementTimeOneStep(); p_simulation_time->IncrementTimeOneStep(); /* Solve the SRN. */ p_srn_model->SimulateToCurrentTime(); double current_time = 1.5; TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); /* Now archive the cell-cycle model through its cell. */ CellPtr const p_const_cell = p_cell; std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); output_arch << p_const_cell; } /* Now create an input archive. Begin by again destroying the current * instance of {{{SimulationTime}}} and creating another instance. Set * the start time, end time and number of time steps. note that this is * overwritten when you load the archive. */ { SimulationTime::Destroy(); SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(0.0); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(1.0, 1); TS_ASSERT_DELTA(p_simulation_time->GetTime(), 0.0, 1e-4); /* Create a pointer to a cell. */ CellPtr p_cell; /* Create an input archive and restore the cell from the archive. */ std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); input_arch >> p_cell; /* Test that the state of the ODES has been restored correctly. */ double current_time = 1.5; TS_ASSERT_DELTA(p_simulation_time->GetTime(), current_time, 1e-4); TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); /* Move forward two more time steps. */ p_simulation_time->IncrementTimeOneStep(); p_simulation_time->IncrementTimeOneStep(); /* Solve the SRN. */ p_cell->GetSrnModel()->SimulateToCurrentTime(); /* Check it's moved on OK */ current_time = 3.0; TS_ASSERT_DELTA(p_simulation_time->GetTime(), current_time, 1e-4); TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); } }
/** * 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(); }
/* * === Using the cell property in a cell-based simulation === * * We conclude with a brief test demonstrating how {{{MotileCellProperty}}} can be used * in a cell-based simulation. */ void TestOffLatticeSimulationWithMotileCellProperty() throw(Exception) { /* Note that HoneycombMeshGenerator, used in this test, is not * yet implemented in parallel. */ /* We use the {{{HoneycombMeshGenerator}}} to create a honeycomb mesh covering a * circular domain of given radius, and use this to generate a {{{NodesOnlyMesh}}} * as follows. */ HoneycombMeshGenerator generator(10, 10); MutableMesh<2,2>* p_generating_mesh = generator.GetCircularMesh(5); NodesOnlyMesh<2> mesh; /* We construct the mesh using the generating mesh and a cut-off 1.5 which defines the * connectivity in the mesh. */ mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); /* We now create a shared pointer to our new property, as follows. */ MAKE_PTR(MotileCellProperty, p_motile); /* * Also create a shared pointer to a cell label so we can visualize the * different cell types. Note that this is also a {{{CellProperty}}}. */ MAKE_PTR(CellLabel, p_label); /* Next, we create some cells. We don't use a Generator as we want to give some cells the new cell property, therefore * we create the cells in a loop, as follows.*/ MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { /* For each node we create a cell with our cell-cycle model and the wild-type cell mutation state. * We then add the property {{{MotileCellProperty}}} to a random selection of the cells, as follows. */ FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPropertyCollection collection; if (RandomNumberGenerator::Instance()->ranf() < 0.2) { collection.AddProperty(p_motile); collection.AddProperty(p_label); } CellPtr p_cell(new Cell(p_state, p_model, false, collection)); p_cell->SetCellProliferativeType(p_diff_type); /* Now, we define a random birth time, chosen from [-T,0], where * T = t,,1,, + t,,2,,, where t,,1,, is a parameter representing the G,,1,, duration * of a stem cell, and t,,2,, is the basic S+G,,2,,+M phases duration. */ double birth_time = - RandomNumberGenerator::Instance()->ranf() * (p_model->GetStemCellG1Duration() + p_model->GetSG2MDuration()); /* Finally, we set the birth time and push the cell back into the vector of cells. */ p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } /* Now that we have defined the mesh and cells, we can define the cell population. The constructor * takes in the mesh and the cells vector. */ NodeBasedCellPopulation<2> cell_population(mesh, cells); /* In order to visualize labelled cells we need to use the following command.*/ cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>(); /* We then pass in the cell population into an {{{OffLatticeSimulation}}}, * and set the output directory, output multiple, and end time. */ OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithMotileCellProperty"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); /* We create a force law and pass it to the {{{OffLatticeSimulation}}}. */ MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); /* Now create a {{{MotlieForce}}} and pass it to the {{{OffLatticeSimulation}}}. */ MAKE_PTR(MyMotiveForce, p_motive_force); simulator.AddForce(p_motive_force); /* To run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); }
/** * \todo WntBasedChemotaxis should be possible in other force laws. If/when * this is implemented, this test should be moved to somewhere more appropriate. */ void TestCryptProjectionForceWithWntBasedChemotaxis() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenerator doesnt work in parallel. double crypt_length = 22.0; // Create a mesh unsigned num_cells_width = 10; unsigned num_cells_depth = 10; unsigned thickness_of_ghost_layer = 0; SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0,1); HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, thickness_of_ghost_layer); MutableMesh<2,2>* p_mesh = generator.GetMesh(); // Centre the mesh at (0,0) 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); // Create some cells std::vector<CellPtr> cells; boost::shared_ptr<AbstractCellMutationState> p_state(new WildTypeCellMutationState); boost::shared_ptr<AbstractCellProperty> p_stem_type(new StemCellProliferativeType); for (unsigned i=0; i<p_mesh->GetNumNodes(); i++) { FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_stem_type); p_cell->SetBirthTime(-10.0); cells.push_back(p_cell); } // Create a cell population MeshBasedCellPopulation<2> cell_population(*p_mesh, cells); std::pair<CellPtr,CellPtr> cell_pair_4_5 = cell_population.CreateCellPair(cell_population.GetCellUsingLocationIndex(4), cell_population.GetCellUsingLocationIndex(5)); cell_population.MarkSpring(cell_pair_4_5); WntConcentration<2>::Instance()->SetType(RADIAL); WntConcentration<2>::Instance()->SetCellPopulation(cell_population); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); // Create a spring system with crypt surface z = 2*r WntConcentration<2>::Instance()->SetCryptProjectionParameterA(2.0); WntConcentration<2>::Instance()->SetCryptProjectionParameterB(1.0); CryptProjectionForce crypt_projection_force; crypt_projection_force.SetWntChemotaxis(false); for (unsigned i=0; i<cell_population.GetNumNodes(); i++) { cell_population.GetNode(i)->ClearAppliedForce(); } // Calculate node forces crypt_projection_force.AddForceContribution(cell_population); // Store the force of a particular node without Wnt-chemotaxis c_vector<double,2> old_force; old_force[0] = cell_population.GetNode(11)->rGetAppliedForce()[0]; old_force[1] = cell_population.GetNode(11)->rGetAppliedForce()[1]; // Now turn on Wnt-chemotaxis crypt_projection_force.SetWntChemotaxis(true); for (unsigned i=0; i<cell_population.GetNumNodes(); i++) { cell_population.GetNode(i)->ClearAppliedForce(); } // Calculate node forces crypt_projection_force.AddForceContribution(cell_population); // Store the force of the same node, but now with Wnt-chemotaxis c_vector<double,2> new_force = cell_population.GetNode(11)->rGetAppliedForce(); double wnt_chemotaxis_strength = crypt_projection_force.GetWntChemotaxisStrength(); CellPtr p_cell = cell_population.GetCellUsingLocationIndex(11u); c_vector<double,2> wnt_component = wnt_chemotaxis_strength*WntConcentration<2>::Instance()->GetWntGradient(p_cell); TS_ASSERT_DELTA(new_force[0], old_force[0]+wnt_component[0], 1e-4); TS_ASSERT_DELTA(new_force[1], old_force[1]+wnt_component[1], 1e-4); WntConcentration<2>::Destroy(); }
/** * Test that post-#878, WntConcentration copes with a VertexBasedCellPopulation. * \todo When vertex-based cell population code is added to cell_based folder, move this * test to TestWntConcentration.hpp */ void TestWntConcentrationWithVertexBasedCellPopulation() throw(Exception) { // Make some nodes std::vector<Node<2>*> nodes; nodes.push_back(new Node<2>(0, true, 2.0, -1.0)); nodes.push_back(new Node<2>(1, true, 2.0, 1.0)); nodes.push_back(new Node<2>(2, true, -2.0, 1.0)); nodes.push_back(new Node<2>(3, true, -2.0, -1.0)); nodes.push_back(new Node<2>(4, true, 0.0, 2.0)); // Make a rectangular element out of nodes 0,1,2,3 std::vector<Node<2>*> nodes_elem_1; nodes_elem_1.push_back(nodes[0]); nodes_elem_1.push_back(nodes[1]); nodes_elem_1.push_back(nodes[2]); nodes_elem_1.push_back(nodes[3]); // Make a triangular element out of nodes 1,4,2 std::vector<Node<2>*> nodes_elem_2; nodes_elem_2.push_back(nodes[1]); nodes_elem_2.push_back(nodes[4]); nodes_elem_2.push_back(nodes[2]); std::vector<VertexElement<2,2>*> vertex_elements; vertex_elements.push_back(new VertexElement<2,2>(0, nodes_elem_1)); vertex_elements.push_back(new VertexElement<2,2>(1, nodes_elem_2)); // Make a vertex mesh MutableVertexMesh<2,2> vertex_mesh(nodes, vertex_elements); // Create cells std::vector<CellPtr> cells; MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); for (unsigned i=0; i<vertex_mesh.GetNumElements(); i++) { WntCellCycleModel* p_cell_cycle_model = new WntCellCycleModel; p_cell_cycle_model->SetDimension(2); CellPtr p_cell(new Cell(p_state, p_cell_cycle_model)); p_cell->SetCellProliferativeType(p_diff_type); double birth_time = 0.0 - i; p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } // Create cell population VertexBasedCellPopulation<2> cell_population(vertex_mesh, cells); // Set the top of this cell_population, for the purposes of computing the WntConcentration double crypt_length = 4.0; // Set up an instance of the WntConcentration singleton object WntConcentration<2>* p_wnt = WntConcentration<2>::Instance(); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), false); // Check that the singleton can be set up p_wnt->SetType(LINEAR); p_wnt->SetCellPopulation(cell_population); p_wnt->SetCryptLength(crypt_length); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), true); // Check that the singleton can be destroyed then recreated WntConcentration<2>::Destroy(); WntConcentration<2>::Instance()->SetType(NONE); WntConcentration<2>::Instance()->SetCellPopulation(cell_population); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); TS_ASSERT_EQUALS(WntConcentration<2>::Instance()->IsWntSetUp(), false); // not fully set up now it is a NONE type WntConcentration<2>::Destroy(); WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetCellPopulation(cell_population); WntConcentration<2>::Instance()->SetCryptLength(crypt_length); p_wnt = WntConcentration<2>::Instance(); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), true); // set up again double wnt_at_cell0 = p_wnt->GetWntLevel(cell_population.GetCellUsingLocationIndex(0)); double wnt_at_cell1 = p_wnt->GetWntLevel(cell_population.GetCellUsingLocationIndex(1)); // We have set the top of the cell population to be 4, so the WntConcentration should decrease linearly // up the cell_population, from one at height 0 to zero at height 4. // Cell 0 has centre of mass (0,0) TS_ASSERT_DELTA(wnt_at_cell0, 1.0, 1e-4); // Cell 1 has centre of mass (0, 4/3) TS_ASSERT_DELTA(wnt_at_cell1, 2.0/3.0, 1e-4); }
void TestCryptProjectionForceWithArchiving() throw (Exception) { EXIT_IF_PARALLEL; // Cell-based archiving doesn't work in parallel. OutputFileHandler handler("archive", false); // don't erase contents of folder std::string archive_filename = handler.GetOutputDirectoryFullPath() + "crypt_projection_spring_system.arch"; { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements"); MutableMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0,1); std::vector<CellPtr> cells; boost::shared_ptr<AbstractCellMutationState> p_state(new WildTypeCellMutationState); boost::shared_ptr<AbstractCellProperty> p_stem_type(new StemCellProliferativeType); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); p_cell->SetCellProliferativeType(p_stem_type); p_cell->SetBirthTime(-50.0); cells.push_back(p_cell); } MeshBasedCellPopulation<2> crypt(mesh, cells); WntConcentration<2>::Instance()->SetCryptProjectionParameterA(1.0); WntConcentration<2>::Instance()->SetCryptProjectionParameterB(2.0); // Create force object CryptProjectionForce crypt_projection_force; TS_ASSERT_DELTA(crypt_projection_force.GetWntChemotaxisStrength(), 100.0, 1e-6); crypt_projection_force.SetWntChemotaxisStrength(15.0); std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); // Serialize via pointer CryptProjectionForce* const p_crypt_projection_force = &crypt_projection_force; p_crypt_projection_force->SetCutOffLength(1.1); output_arch << p_crypt_projection_force; WntConcentration<2>::Destroy(); } { ArchiveLocationInfo::SetMeshPathname("mesh/test/data/", "square_2_elements"); // Create an input archive std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); CryptProjectionForce* p_crypt_projection_force; // Restore from the archive input_arch >> p_crypt_projection_force; // Test the member data TS_ASSERT_EQUALS(p_crypt_projection_force->mUseCutOffLength, true); TS_ASSERT_DELTA(p_crypt_projection_force->GetA(), 1.0, 1e-12); TS_ASSERT_DELTA(p_crypt_projection_force->GetB(), 2.0, 1e-12); TS_ASSERT_DELTA(p_crypt_projection_force->GetWntChemotaxisStrength(), 15.0, 1e-6); delete p_crypt_projection_force; } }