PottsBasedCellPopulation.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "PottsBasedCellPopulation.hpp"
00030 #include "RandomNumberGenerator.hpp"
00031 #include "Warnings.hpp"
00032
00033
00034 #include "VtkMeshWriter.hpp"
00035 #include "NodesOnlyMesh.hpp"
00036 #include "Exception.hpp"
00037
00038 template<unsigned DIM>
00039 void PottsBasedCellPopulation<DIM>::Validate()
00040 {
00041
00042 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00043
00044 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00045 cell_iter != this->End();
00046 ++cell_iter)
00047 {
00048 unsigned elem_index = GetLocationIndexUsingCell(*cell_iter);
00049 validated_element[elem_index]++;
00050 }
00051
00052 for (unsigned i=0; i<validated_element.size(); i++)
00053 {
00054 if (validated_element[i] == 0)
00055 {
00056 EXCEPTION("Element " << i << " does not appear to have a cell associated with it");
00057 }
00058
00059 if (validated_element[i] > 1)
00060 {
00061 EXCEPTION("Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00062 }
00063 }
00064 }
00065
00066 template<unsigned DIM>
00067 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh,
00068 std::vector<CellPtr>& rCells,
00069 bool deleteMesh,
00070 bool validate,
00071 const std::vector<unsigned> locationIndices)
00072 : AbstractOnLatticeCellPopulation<DIM>(rCells, locationIndices, deleteMesh),
00073 mrMesh(rMesh),
00074 mpElementTessellation(NULL),
00075 mTemperature(0.1),
00076 mNumSweepsPerTimestep(1)
00077 {
00078
00079 if (validate)
00080 {
00081 Validate();
00082 }
00083 }
00084
00085 template<unsigned DIM>
00086 PottsBasedCellPopulation<DIM>::PottsBasedCellPopulation(PottsMesh<DIM>& rMesh)
00087 : AbstractOnLatticeCellPopulation<DIM>(),
00088 mrMesh(rMesh),
00089 mpElementTessellation(NULL),
00090 mTemperature(0.1),
00091 mNumSweepsPerTimestep(1)
00092 {
00093 }
00094
00095 template<unsigned DIM>
00096 PottsBasedCellPopulation<DIM>::~PottsBasedCellPopulation()
00097 {
00098 delete mpElementTessellation;
00099
00100 if (this->mDeleteMesh)
00101 {
00102 delete &mrMesh;
00103 }
00104 }
00105
00106 template<unsigned DIM>
00107 PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh()
00108 {
00109 return mrMesh;
00110 }
00111
00112 template<unsigned DIM>
00113 const PottsMesh<DIM>& PottsBasedCellPopulation<DIM>::rGetMesh() const
00114 {
00115 return mrMesh;
00116 }
00117
00118 template<unsigned DIM>
00119 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00120 {
00121 return mrMesh.GetElement(elementIndex);
00122 }
00123
00124 template<unsigned DIM>
00125 unsigned PottsBasedCellPopulation<DIM>::GetNumElements()
00126 {
00127 return mrMesh.GetNumElements();
00128 }
00129
00130 template<unsigned DIM>
00131 Node<DIM>* PottsBasedCellPopulation<DIM>::GetNode(unsigned index)
00132 {
00133 return mrMesh.GetNode(index);
00134 }
00135
00136 template<unsigned DIM>
00137 unsigned PottsBasedCellPopulation<DIM>::GetNumNodes()
00138 {
00139 return mrMesh.GetNumNodes();
00140 }
00141
00142 template<unsigned DIM>
00143 c_vector<double, DIM> PottsBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00144 {
00145 return mrMesh.GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
00146 }
00147
00148 template<unsigned DIM>
00149 PottsElement<DIM>* PottsBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00150 {
00151 return mrMesh.GetElement(this->mCellLocationMap[pCell.get()]);
00152 }
00153
00154 template<unsigned DIM>
00155 CellPtr PottsBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00156 {
00157
00158 PottsElement<DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00159
00160
00161 unsigned new_element_index = mrMesh.DivideElement(p_element, true);
00162
00163
00164 this->mCells.push_back(pNewCell);
00165
00166
00167 CellPtr p_created_cell = this->mCells.back();
00168 this->mLocationCellMap[new_element_index] = p_created_cell;
00169 this->mCellLocationMap[p_created_cell.get()] = new_element_index;
00170 return p_created_cell;
00171 }
00172
00173 template<unsigned DIM>
00174 unsigned PottsBasedCellPopulation<DIM>::RemoveDeadCells()
00175 {
00176 unsigned num_removed = 0;
00177
00178 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00179 it != this->mCells.end();
00180 ++it)
00181 {
00182 if ((*it)->IsDead())
00183 {
00184
00185 num_removed++;
00186 mrMesh.DeleteElement(this->mCellLocationMap[(*it).get()]);
00187 it = this->mCells.erase(it);
00188 --it;
00189 }
00190 }
00191 return num_removed;
00192 }
00193 template<unsigned DIM>
00194 void PottsBasedCellPopulation<DIM>::UpdateCellLocations(double dt)
00195 {
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00209 unsigned num_nodes = mrMesh.GetNumNodes();
00210
00211
00212 if (this->mIterateRandomlyOverUpdateRuleCollection)
00213 {
00215 std::random_shuffle(mUpdateRuleCollection.begin(), mUpdateRuleCollection.end());
00216 }
00217
00218 for (unsigned i=0; i<num_nodes*mNumSweepsPerTimestep; i++)
00219 {
00220 unsigned node_index;
00221
00222 if (this->mUpdateNodesInRandomOrder)
00223 {
00224 node_index = p_gen->randMod(num_nodes);
00225 }
00226 else
00227 {
00228
00229 node_index = i%num_nodes;
00230 }
00231
00232 Node<DIM>* p_node = mrMesh.GetNode(node_index);
00233
00234
00235 assert(p_node->GetNumContainingElements() <= 1);
00236
00237
00238 std::set<unsigned> neighbouring_node_indices = mrMesh.GetMooreNeighbouringNodeIndices(node_index);
00239 unsigned neighbour_location_index;
00240
00241 if (!neighbouring_node_indices.empty())
00242 {
00243 unsigned num_neighbours = neighbouring_node_indices.size();
00244 unsigned chosen_neighbour = p_gen->randMod(num_neighbours);
00245
00246 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00247 for (unsigned i=0; i<chosen_neighbour; i++)
00248 {
00249 neighbour_iter++;
00250 }
00251
00252 neighbour_location_index = *neighbour_iter;
00253 }
00254 else
00255 {
00256
00257 NEVER_REACHED;
00258 }
00259
00260 std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
00261 std::set<unsigned> neighbour_containing_elements = GetNode(neighbour_location_index)->rGetContainingElementIndices();
00262
00263 if ( ( *containing_elements.begin() != *neighbour_containing_elements.begin() && !containing_elements.empty() && !neighbour_containing_elements.empty() )
00264 || ( !containing_elements.empty() && neighbour_containing_elements.empty() )
00265 || ( containing_elements.empty() && !neighbour_containing_elements.empty() ) )
00266 {
00267 double delta_H = 0.0;
00268
00269
00270 for (typename std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >::iterator iter = mUpdateRuleCollection.begin();
00271 iter != mUpdateRuleCollection.end();
00272 ++iter)
00273 {
00274 delta_H += (*iter)->EvaluateHamiltonianContribution(neighbour_location_index, p_node->GetIndex(), *this);
00275 }
00276
00277
00278 double random_number = p_gen->ranf();
00279 double p = exp(-delta_H/mTemperature);
00280 if (delta_H <= 0 || random_number < p)
00281 {
00282
00283
00284
00285 for (std::set<unsigned>::iterator iter = containing_elements.begin();
00286 iter != containing_elements.end();
00287 ++iter)
00288 {
00289 GetElement(*iter)->DeleteNode(GetElement(*iter)->GetNodeLocalIndex(node_index));
00290
00292 }
00293
00294
00295 for (std::set<unsigned>::iterator iter = neighbour_containing_elements.begin();
00296 iter != neighbour_containing_elements.end();
00297 ++iter)
00298 {
00299 GetElement(*iter)->AddNode(mrMesh.GetNode(node_index));
00300 }
00301 }
00302 }
00303 }
00304 }
00305
00306 template<unsigned DIM>
00307 bool PottsBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00308 {
00309 return GetElementCorrespondingToCell(pCell)->IsDeleted();
00310 }
00311
00312 template<unsigned DIM>
00313 void PottsBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00314 {
00315 }
00316
00317 template<unsigned DIM>
00318 void PottsBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00319 {
00320 AbstractCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00321
00322 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00323 mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00324 }
00325
00326 template<unsigned DIM>
00327 void PottsBasedCellPopulation<DIM>::CloseOutputFiles()
00328 {
00329 AbstractCellPopulation<DIM>::CloseOutputFiles();
00330 mpVizElementsFile->close();
00331 }
00332
00333 template<unsigned DIM>
00334 void PottsBasedCellPopulation<DIM>::WriteResultsToFiles()
00335 {
00336 AbstractCellPopulation<DIM>::WriteResultsToFiles();
00337
00338 CreateElementTessellation();
00339
00340 SimulationTime* p_time = SimulationTime::Instance();
00341
00342
00343 *mpVizElementsFile << p_time->GetTime() << "\t";
00344
00345
00346 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00347 cell_iter != this->mCells.end();
00348 ++cell_iter)
00349 {
00350 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00351
00352
00353 bool elem_corresponds_to_dead_cell = false;
00354
00355 if (this->mLocationCellMap[elem_index])
00356 {
00357 elem_corresponds_to_dead_cell = this->mLocationCellMap[elem_index]->IsDead();
00358 }
00359
00360
00361 if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00362 {
00363 PottsElement<DIM>* p_element = mrMesh.GetElement(elem_index);
00364
00365 unsigned num_nodes_in_element = p_element->GetNumNodes();
00366
00367
00368 *mpVizElementsFile << num_nodes_in_element << " ";
00369
00370
00371 for (unsigned i=0; i<num_nodes_in_element; i++)
00372 {
00373 *mpVizElementsFile << p_element->GetNodeGlobalIndex(i) << " ";
00374 }
00375 }
00376 }
00377 *mpVizElementsFile << "\n";
00378 }
00379
00380 template<unsigned DIM>
00381 void PottsBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00382 {
00383
00384 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00385
00386
00387 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00388 cell_iter != this->End();
00389 ++cell_iter)
00390 {
00391 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00392
00393
00394 bool elem_corresponds_to_dead_cell = false;
00395
00396 if (this->mLocationCellMap[elem_index])
00397 {
00398 elem_corresponds_to_dead_cell = this->mLocationCellMap[elem_index]->IsDead();
00399 }
00400
00401
00402 if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00403 {
00404
00405 *(this->mpCellVolumesFile) << elem_index << " ";
00406
00407
00408 unsigned cell_index = cell_iter->GetCellId();
00409 *(this->mpCellVolumesFile) << cell_index << " ";
00410
00411
00412 c_vector<double, DIM> centroid_location = mrMesh.GetCentroidOfElement(elem_index);
00413
00414 *(this->mpCellVolumesFile) << centroid_location[0] << " ";
00415 *(this->mpCellVolumesFile) << centroid_location[1] << " ";
00416
00417
00418 double cell_volume = mrMesh.GetVolumeOfElement(elem_index);
00419 *(this->mpCellVolumesFile) << cell_volume << " ";
00420 }
00421 }
00422 *(this->mpCellVolumesFile) << "\n";
00423 }
00424
00425 template<unsigned DIM>
00426 void PottsBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles()
00427 {
00428
00429 unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00430 std::vector<unsigned> cell_type_counter(num_cell_types);
00431 for (unsigned i=0; i<num_cell_types; i++)
00432 {
00433 cell_type_counter[i] = 0;
00434 }
00435
00436
00437 unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00438 std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00439 for (unsigned i=0; i<num_cell_cycle_phases; i++)
00440 {
00441 cell_cycle_phase_counter[i] = 0;
00442 }
00443
00444 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00445 cell_iter != this->End();
00446 ++cell_iter)
00447 {
00448 this->GenerateCellResults(this->GetLocationIndexUsingCell(*cell_iter), cell_type_counter, cell_cycle_phase_counter);
00449 }
00450
00451 this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00452 }
00453
00454 template<unsigned DIM>
00455 double PottsBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00456 {
00457
00458 double width = mrMesh.GetWidth(rDimension);
00459
00460 return width;
00461 }
00462
00463 template<unsigned DIM>
00464 void PottsBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractPottsUpdateRule<DIM> > pUpdateRule)
00465 {
00466 mUpdateRuleCollection.push_back(pUpdateRule);
00467 }
00468
00469 template<unsigned DIM>
00470 const std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >& PottsBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
00471 {
00472 return mUpdateRuleCollection;
00473 }
00474
00475 template<unsigned DIM>
00476 void PottsBasedCellPopulation<DIM>::CreateElementTessellation()
00477 {
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 }
00492
00493 template<unsigned DIM>
00494 VertexMesh<DIM,DIM>* PottsBasedCellPopulation<DIM>::GetElementTessellation()
00495 {
00496
00497 return mpElementTessellation;
00498 }
00499
00500 template<unsigned DIM>
00501 void PottsBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00502 {
00503 *rParamsFile << "\t\t<Temperature>" << mTemperature << "</Temperature>\n";
00504 *rParamsFile << "\t\t<NumSweepsPerTimestep>" << mNumSweepsPerTimestep << "</NumSweepsPerTimestep>\n";
00505
00506
00507 AbstractOnLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00508 }
00509
00510 template<unsigned DIM>
00511 std::set<unsigned> PottsBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00512 {
00513 EXCEPTION("Cannot call GetNeighbouringNodeIndices() on a PottsBasedCellPopulation, need to go through the PottsMesh instead");
00514 std::set<unsigned> neighbouring_node_indices;
00515 return neighbouring_node_indices;
00516 }
00517
00518 template<unsigned DIM>
00519 void PottsBasedCellPopulation<DIM>::SetTemperature(double temperature)
00520 {
00521 mTemperature = temperature;
00522 }
00523
00524 template<unsigned DIM>
00525 double PottsBasedCellPopulation<DIM>::GetTemperature()
00526 {
00527 return mTemperature;
00528 }
00529
00530 template<unsigned DIM>
00531 void PottsBasedCellPopulation<DIM>::SetNumSweepsPerTimestep(unsigned numSweepsPerTimestep)
00532 {
00533 mNumSweepsPerTimestep = numSweepsPerTimestep;
00534 }
00535
00536 template<unsigned DIM>
00537 unsigned PottsBasedCellPopulation<DIM>::GetNumSweepsPerTimestep()
00538 {
00539 return mNumSweepsPerTimestep;
00540 }
00541
00542 template<unsigned DIM>
00543 void PottsBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00544 {
00545 #ifdef CHASTE_VTK
00546 std::stringstream time;
00547 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00548 VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00549
00550 unsigned num_nodes = GetNumNodes();
00551 std::vector<double> cell_types;
00552 std::vector<double> cell_mutation_states;
00553 std::vector<double> cell_labels;
00554 std::vector<double> elem_ids;
00555 cell_types.reserve(num_nodes);
00556 cell_mutation_states.reserve(num_nodes);
00557 cell_labels.reserve(num_nodes);
00558 elem_ids.reserve(num_nodes);
00559
00560 for (typename AbstractMesh<DIM,DIM>::NodeIterator iter = mrMesh.GetNodeIteratorBegin();
00561 iter != mrMesh.GetNodeIteratorEnd();
00562 ++iter)
00563 {
00564 std::set<unsigned> element_indices = iter->rGetContainingElementIndices();
00565
00566 if (element_indices.empty())
00567 {
00568
00569 cell_types.push_back(-1.0);
00570 elem_ids.push_back(-1.0);
00571 if (this->mOutputCellMutationStates)
00572 {
00573 cell_mutation_states.push_back(-1.0);
00574 cell_labels.push_back(-1.0);
00575 }
00576 }
00577 else
00578 {
00579
00580 assert(element_indices.size() == 1);
00581
00582 unsigned element_index = *(element_indices.begin());
00583 elem_ids.push_back((double)element_index);
00584
00585 CellPtr p_cell = this->mLocationCellMap[element_index];
00586 double cell_type = p_cell->GetCellCycleModel()->GetCellProliferativeType();
00587 cell_types.push_back(cell_type);
00588
00589 if (this->mOutputCellMutationStates)
00590 {
00591 double cell_mutation_state = p_cell->GetMutationState()->GetColour();
00592 cell_mutation_states.push_back(cell_mutation_state);
00593
00594 double cell_label = 0.0;
00595 if (p_cell->HasCellProperty<CellLabel>())
00596 {
00597 CellPropertyCollection collection = p_cell->rGetCellPropertyCollection().GetProperties<CellLabel>();
00598 boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(collection.GetProperty());
00599 cell_label = p_label->GetColour();
00600 }
00601 cell_labels.push_back(cell_label);
00602 }
00603 }
00604 }
00605
00606 assert(cell_types.size() == num_nodes);
00607 assert(elem_ids.size() == num_nodes);
00608
00609 mesh_writer.AddPointData("Element index", elem_ids);
00610 mesh_writer.AddPointData("Cell types", cell_types);
00611
00612 if (this->mOutputCellMutationStates)
00613 {
00614 assert(cell_mutation_states.size() == num_nodes);
00615 mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00616 assert(cell_labels.size() == num_nodes);
00617 mesh_writer.AddPointData("Cell labels", cell_labels);
00618 }
00619
00620
00621
00622
00623
00624 NodesOnlyMesh<DIM> temp_mesh;
00625 temp_mesh.ConstructNodesWithoutMesh(mrMesh);
00626 mesh_writer.WriteFilesUsingMesh(temp_mesh);
00627
00628 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00629 *(this->mpVtkMetaFile) << time.str();
00630 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00631 *(this->mpVtkMetaFile) << time.str();
00632 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00633 #endif //CHASTE_VTK
00634 }
00635
00637
00639
00640 template class PottsBasedCellPopulation<1>;
00641 template class PottsBasedCellPopulation<2>;
00642 template class PottsBasedCellPopulation<3>;
00643
00644
00645 #include "SerializationExportWrapperForCpp.hpp"
00646 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsBasedCellPopulation)