Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "MultipleCaBasedCellPopulation.hpp" 00037 #include "RandomNumberGenerator.hpp" 00038 #include "Warnings.hpp" 00039 00040 // Needed to convert mesh in order to write nodes to VTK (visualize as glyphs) 00041 #include "VtkMeshWriter.hpp" 00042 #include "NodesOnlyMesh.hpp" 00043 #include "Exception.hpp" 00044 00045 template<unsigned DIM> 00046 void MultipleCaBasedCellPopulation<DIM>::Validate() 00047 { 00048 NEVER_REACHED; 00049 } 00050 00051 template<unsigned DIM> 00052 MultipleCaBasedCellPopulation<DIM>::MultipleCaBasedCellPopulation(PottsMesh<DIM>& rMesh, 00053 std::vector<CellPtr>& rCells, 00054 const std::vector<unsigned> locationIndices, 00055 unsigned latticeCarryingCapacity, 00056 bool deleteMesh, 00057 bool validate) 00058 : AbstractOnLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh), 00059 mLatticeCarryingCapacity(latticeCarryingCapacity) 00060 { 00061 mAvailableSpaces = std::vector<unsigned>(this->GetNumNodes(), latticeCarryingCapacity); 00062 00063 // This must always be true 00064 assert(this->mCells.size() <= this->mrMesh.GetNumNodes()*latticeCarryingCapacity); 00065 00066 if (locationIndices.empty()) 00067 { 00068 EXCEPTION("No location indices being passed. Specify where cells lie before creating the cell population."); 00069 } 00070 else 00071 { 00072 // Create a set of node indices corresponding to empty sites 00073 for (unsigned i=0; i<locationIndices.size(); i++) 00074 { 00075 if (mAvailableSpaces[locationIndices[i]] == 0u) 00076 { 00077 EXCEPTION("One of the lattice sites has more cells than the carrying capacity. Check the initial cell locations."); 00078 } 00079 mAvailableSpaces[locationIndices[i]]--; 00080 } 00081 } 00082 if (validate) 00083 { 00084 EXCEPTION("There is no validation for MultipleCaBasedCellPopulation."); 00085 } 00086 } 00087 00088 template<unsigned DIM> 00089 MultipleCaBasedCellPopulation<DIM>::MultipleCaBasedCellPopulation(PottsMesh<DIM>& rMesh) 00090 : AbstractOnLatticeCellPopulation<DIM>(rMesh) 00091 { 00092 } 00093 00094 template<unsigned DIM> 00095 MultipleCaBasedCellPopulation<DIM>::~MultipleCaBasedCellPopulation() 00096 { 00097 00098 // This is not needed unles we are de-serializing the cell population 00099 // if (this->mDeleteMesh) 00100 // { 00101 // delete &this->mrMesh; 00102 // } 00103 } 00104 00105 00106 template<unsigned DIM> 00107 std::vector<unsigned>& MultipleCaBasedCellPopulation<DIM>::rGetAvailableSpaces() 00108 { 00109 return mAvailableSpaces; 00110 } 00111 00112 template<unsigned DIM> 00113 bool MultipleCaBasedCellPopulation<DIM>::IsSiteAvailable(unsigned index) 00114 { 00115 return (mAvailableSpaces[index]>0u); 00116 } 00117 00118 template<unsigned DIM> 00119 PottsMesh<DIM>& MultipleCaBasedCellPopulation<DIM>::rGetMesh() 00120 { 00121 return static_cast<PottsMesh<DIM>& >((this->mrMesh)); 00122 } 00123 00124 template<unsigned DIM> 00125 const PottsMesh<DIM>& MultipleCaBasedCellPopulation<DIM>::rGetMesh() const 00126 { 00127 return static_cast<PottsMesh<DIM>& >((this->mrMesh)); 00128 } 00129 00130 template<unsigned DIM> 00131 Node<DIM>* MultipleCaBasedCellPopulation<DIM>::GetNode(unsigned index) 00132 { 00133 return this->mrMesh.GetNode(index); 00134 } 00135 00136 template<unsigned DIM> 00137 unsigned MultipleCaBasedCellPopulation<DIM>::GetNumNodes() 00138 { 00139 return this->mrMesh.GetNumNodes(); 00140 } 00141 00142 template<unsigned DIM> 00143 c_vector<double, DIM> MultipleCaBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell) 00144 { 00145 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell))->rGetLocation(); 00146 } 00147 00148 template<unsigned DIM> 00149 Node<DIM>* MultipleCaBasedCellPopulation<DIM>::GetNodeCorrespondingToCell(CellPtr pCell) 00150 { 00151 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell)); 00152 } 00153 00154 template<unsigned DIM> 00155 void MultipleCaBasedCellPopulation<DIM>::AddCellUsingLocationIndex(unsigned index, CellPtr pCell) 00156 { 00157 if (mAvailableSpaces[index]==0u) 00158 { 00159 EXCEPTION("No available spaces at location index " << index << "."); 00160 } 00161 mAvailableSpaces[index]--; 00162 AbstractCellPopulation<DIM,DIM>::AddCellUsingLocationIndex(index, pCell); 00163 } 00164 00165 template<unsigned DIM> 00166 void MultipleCaBasedCellPopulation<DIM>::RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell) 00167 { 00168 AbstractCellPopulation<DIM,DIM>::RemoveCellUsingLocationIndex(index, pCell); 00169 00170 mAvailableSpaces[index]++; 00171 00172 assert(mAvailableSpaces[index]<=mLatticeCarryingCapacity); 00173 } 00174 00175 template<unsigned DIM> 00176 CellPtr MultipleCaBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell) 00177 { 00178 // Get node index corresponding to the parent cell 00179 unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell); 00180 00181 // Get the set of neighbouring node indices 00182 std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(parent_node_index); 00183 00184 assert(!neighbouring_node_indices.empty()); 00185 00186 unsigned num_neighbours = neighbouring_node_indices.size(); 00187 00188 // double prob_dividing_into_this_site = GetProbabilityOfDivisionIntoTargetSite(parent_node_index, ??, num_neighbours); 00189 00190 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance(); 00191 unsigned chosen_start = p_gen->randMod(num_neighbours); 00192 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin(); 00193 00194 for (unsigned i=0; i<chosen_start; i++) 00195 { 00196 neighbour_iter++; 00197 } 00198 00199 unsigned daughter_node_index = UNSIGNED_UNSET; 00200 00201 unsigned count = 0; 00202 while (count < num_neighbours) 00203 { 00204 bool is_empty_site = IsSiteAvailable(*neighbour_iter); 00205 00206 if (is_empty_site) 00207 { 00208 daughter_node_index = *neighbour_iter; 00209 break; 00210 } 00211 else 00212 { 00213 neighbour_iter++; 00214 00215 if (neighbour_iter == neighbouring_node_indices.end()) 00216 { 00217 neighbour_iter = neighbouring_node_indices.begin(); 00218 } 00219 00220 count++; 00221 } 00222 } 00223 00224 if (daughter_node_index == UNSIGNED_UNSET) 00225 { 00226 EXCEPTION("No free space to divide."); 00227 } 00228 00229 // Associate the new cell with the element 00230 this->mCells.push_back(pNewCell); 00231 00232 // Update location cell map 00233 CellPtr p_created_cell = this->mCells.back(); 00234 AddCellUsingLocationIndex(daughter_node_index,p_created_cell); 00235 00236 return p_created_cell; 00237 } 00238 00239 template<unsigned DIM> 00240 unsigned MultipleCaBasedCellPopulation<DIM>::RemoveDeadCells() 00241 { 00242 unsigned num_removed = 0; 00243 00244 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00245 cell_iter != this->mCells.end(); 00246 ++cell_iter) 00247 { 00248 if ((*cell_iter)->IsDead()) 00249 { 00250 // Get the index of the node corresponding to this cell 00251 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00252 00253 RemoveCellUsingLocationIndex(node_index, (*cell_iter)); 00254 00255 // Erase cell and update counter 00256 num_removed++; 00257 cell_iter = this->mCells.erase(cell_iter); 00258 --cell_iter; 00259 } 00260 } 00261 return num_removed; 00262 } 00263 00264 template<unsigned DIM> 00265 void MultipleCaBasedCellPopulation<DIM>::UpdateCellLocations(double dt) 00266 { 00267 /* 00268 * Iterate over cells \todo make this sweep random 00269 */ 00270 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00271 cell_iter != this->mCells.end(); 00272 ++cell_iter) 00273 { 00274 00275 /* 00276 * Loop over neighbours and calculate probability of moving (make sure all probabilities are <1) 00277 */ 00278 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00279 00280 // Find a random available neighbouring node to overwrite current site 00281 std::set<unsigned> neighbouring_node_indices = static_cast<PottsMesh<DIM>& >((this->mrMesh)).GetMooreNeighbouringNodeIndices(node_index); 00282 std::vector<double> neighbouring_node_propensities; 00283 std::vector<double> neighbouring_node_indices_vector; 00284 00285 if (!neighbouring_node_indices.empty()) 00286 { 00287 //neighbouring_node_indices_list.sort(); 00288 unsigned num_neighbours = neighbouring_node_indices.size(); 00289 double probability_of_not_moving = 1.0; 00290 double probability_of_moving = 0.0; 00291 00292 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin(); 00293 iter != neighbouring_node_indices.end(); 00294 ++iter) 00295 { 00296 neighbouring_node_indices_vector.push_back(*iter); 00297 00298 if (IsSiteAvailable(*iter)) 00299 { 00300 // Iterating over the update rule 00301 for (typename std::vector<boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > >::iterator iterRule = mUpdateRuleCollection.begin(); 00302 iterRule != mUpdateRuleCollection.end(); 00303 ++iterRule) 00304 { 00305 probability_of_moving = (*iterRule)->EvaluateProbability(node_index, *iter, *this, dt, 1); 00306 if (probability_of_moving < 0) 00307 { 00308 EXCEPTION("The probability of cellular movement is smaller than zero. In order to prevent it from happening you should change your time step and parameters"); 00309 } 00310 00311 if (probability_of_moving > 1) 00312 { 00313 EXCEPTION("The probability of the cellular movement is bigger than one. In order to prevent it from happening you should change your time step and parameters"); 00314 } 00315 } 00316 00317 probability_of_not_moving -= probability_of_moving; 00318 neighbouring_node_propensities.push_back(probability_of_moving); 00319 } 00320 else 00321 { 00322 neighbouring_node_propensities.push_back(0.0); 00323 } 00324 } 00325 if (probability_of_not_moving < 0) 00326 { 00327 EXCEPTION("The probability of the cell not moving is smaller than zero. In order to prevent it from happening you should change your time step and parameters"); 00328 } 00329 00330 /* 00331 * Sample random number to specify which move to make 00332 */ 00333 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance(); 00334 double random_number = p_gen->ranf(); 00335 00336 double total_probability = 0.0; 00337 for (unsigned counter=0; counter<num_neighbours; counter++) 00338 { 00339 total_probability += neighbouring_node_propensities[counter]; 00340 if (total_probability >= random_number) 00341 { 00342 //Move the cell to this neighbour location 00343 unsigned chosen_neighbour_location_index = neighbouring_node_indices_vector[counter]; 00344 this->MoveCellInLocationMap((*cell_iter), node_index, chosen_neighbour_location_index); 00345 break; 00346 } 00347 } 00348 //If loop completes with total_probability < random_number then stay in the same location 00349 } 00350 else 00351 { 00352 // Each node in the mesh must have at least one neighbour 00353 NEVER_REACHED; 00354 } 00355 00356 00357 } 00358 } 00359 00360 template<unsigned DIM> 00361 bool MultipleCaBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell) 00362 { 00363 return false; 00364 } 00365 00366 template<unsigned DIM> 00367 void MultipleCaBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths) 00368 { 00369 } 00370 00371 template<unsigned DIM> 00372 void MultipleCaBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory) 00373 { 00374 AbstractCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory); 00375 00376 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory); 00377 mpVizLocationsFile = output_file_handler.OpenOutputFile("results.vizlocations"); 00378 } 00379 00380 template<unsigned DIM> 00381 void MultipleCaBasedCellPopulation<DIM>::CloseOutputFiles() 00382 { 00383 AbstractCellPopulation<DIM>::CloseOutputFiles(); 00384 mpVizLocationsFile->close(); 00385 } 00386 00387 template<unsigned DIM> 00388 void MultipleCaBasedCellPopulation<DIM>::WriteResultsToFiles() 00389 { 00390 00391 AbstractCellPopulation<DIM>::WriteResultsToFiles(); 00392 00393 SimulationTime* p_time = SimulationTime::Instance(); 00394 00395 // Write location data to file 00396 *mpVizLocationsFile << p_time->GetTime() << "\t"; 00397 00398 // Loop over cells and find associated nodes so in the same order as the cells in output files 00399 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00400 cell_iter != this->mCells.end(); 00401 ++cell_iter) 00402 { 00403 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00404 00405 // Write the index of the of Node the cell is associated with. 00406 *mpVizLocationsFile << node_index << " "; 00407 } 00408 *mpVizLocationsFile << "\n"; 00409 00410 } 00411 00412 template<unsigned DIM> 00413 void MultipleCaBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile() 00414 { 00415 // Write time to file 00416 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " "; 00417 00418 // Loop over cells 00419 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00420 cell_iter != this->End(); 00421 ++cell_iter) 00422 { 00423 // Get the index of the corresponding node in mrMesh and write to file 00424 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00425 *(this->mpCellVolumesFile) << node_index << " "; 00426 00427 // Get cell ID and write to file 00428 unsigned cell_index = cell_iter->GetCellId(); 00429 *(this->mpCellVolumesFile) << cell_index << " "; 00430 00431 // Get node location and write to file 00432 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation(); 00433 for (unsigned i=0; i<DIM; i++) 00434 { 00435 *(this->mpCellVolumesFile) << node_location[i] << " "; 00436 } 00437 00438 // Write cell volume (in 3D) or area (in 2D) to file 00439 double cell_volume = this->GetVolumeOfCell(*cell_iter); 00440 *(this->mpCellVolumesFile) << cell_volume << " "; 00441 } 00442 *(this->mpCellVolumesFile) << "\n"; 00443 } 00444 00445 template<unsigned DIM> 00446 double MultipleCaBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell) 00447 { 00448 double cell_volume = 1.0; 00449 00450 return cell_volume; 00451 } 00452 00453 template<unsigned DIM> 00454 void MultipleCaBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles() 00455 { 00456 // Set up cell type counter 00457 unsigned num_cell_types = this->mCellProliferativeTypeCount.size(); 00458 std::vector<unsigned> cell_type_counter(num_cell_types); 00459 for (unsigned i=0; i<num_cell_types; i++) 00460 { 00461 cell_type_counter[i] = 0; 00462 } 00463 00464 // Set up cell cycle phase counter 00465 unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size(); 00466 std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases); 00467 for (unsigned i=0; i<num_cell_cycle_phases; i++) 00468 { 00469 cell_cycle_phase_counter[i] = 0; 00470 } 00471 00472 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00473 cell_iter != this->End(); 00474 ++cell_iter) 00475 { 00476 this->GenerateCellResults(*cell_iter, cell_type_counter, cell_cycle_phase_counter); 00477 } 00478 00479 this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter); 00480 } 00481 00482 template<unsigned DIM> 00483 double MultipleCaBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension) 00484 { 00485 // Call GetWidth() on the mesh 00486 double width = this->mrMesh.GetWidth(rDimension); 00487 00488 return width; 00489 } 00490 00491 template<unsigned DIM> 00492 void MultipleCaBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > pUpdateRule) 00493 { 00494 mUpdateRuleCollection.push_back(pUpdateRule); 00495 } 00496 00497 template<unsigned DIM> 00498 void MultipleCaBasedCellPopulation<DIM>::RemoveAllUpdateRules() 00499 { 00500 mUpdateRuleCollection.clear(); 00501 } 00502 00503 template<unsigned DIM> 00504 const std::vector<boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > >& MultipleCaBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const 00505 { 00506 return mUpdateRuleCollection; 00507 } 00508 00509 template<unsigned DIM> 00510 void MultipleCaBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile) 00511 { 00512 // Call method on direct parent class 00513 AbstractOnLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile); 00514 } 00515 00516 template<unsigned DIM> 00517 std::set<unsigned> MultipleCaBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index) 00518 { 00519 EXCEPTION("Cannot call GetNeighbouringNodeIndices() on a MultipleCaBasedCellPopulation, need to go through the PottsMesh instead"); 00520 std::set<unsigned> neighbouring_node_indices; 00521 return neighbouring_node_indices; 00522 } 00523 00524 template<unsigned DIM> 00525 void MultipleCaBasedCellPopulation<DIM>::WriteVtkResultsToFile() 00526 { 00527 #ifdef CHASTE_VTK 00528 00529 std::stringstream time; 00530 time << SimulationTime::Instance()->GetTimeStepsElapsed(); 00531 VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false); 00532 00533 unsigned num_cells = this->GetNumRealCells(); 00534 std::vector<double> cell_types(num_cells, -1.0); 00535 std::vector<double> cell_mutation_states(num_cells, -1.0); 00536 std::vector<double> cell_labels(num_cells, -1.0); 00537 std::vector<double> cell_ids(num_cells, -1.0); 00538 std::vector<double> cell_ancestors(num_cells, -1.0); 00539 std::vector<double> cell_ages(num_cells, -1.0); 00540 std::vector<double> cell_cycle_phases(num_cells, -1.0); 00541 std::vector<Node<DIM>*> nodes; 00542 00543 unsigned cell = 0u; 00544 00545 for (std::list<CellPtr>::iterator iter = this->mCells.begin(); 00546 iter != this->mCells.end(); 00547 ++iter) 00548 { 00549 CellPtr cell_ptr = *iter; 00550 cell_ids[cell] = cell_ptr->GetCellId(); 00551 00552 c_vector<double, DIM> coords = GetLocationOfCellCentre(*iter); 00553 00554 // Move the coordinate slightly so that we can visualise all cells in a lattice site if there is more than one per site 00555 if (mLatticeCarryingCapacity > 1) 00556 { 00557 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance(); 00558 00559 for (unsigned i=0; i<DIM; i++) 00560 { 00561 coords[i] += p_gen->ranf(); // This assumes that all sites are 1 apart 00562 } 00563 } 00564 00565 nodes.push_back(new Node<DIM>(cell, coords, false)); 00566 00567 if (this->mOutputCellAncestors) 00568 { 00569 double ancestor_index = (cell_ptr->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_ptr->GetAncestor(); 00570 cell_ancestors[cell] = ancestor_index; 00571 } 00572 if (this->mOutputCellProliferativeTypes) 00573 { 00574 cell_types[cell] = cell_ptr->GetCellProliferativeType(); 00575 } 00576 if (this->mOutputCellMutationStates) 00577 { 00578 cell_mutation_states[cell] = cell_ptr->GetMutationState()->GetColour(); 00579 } 00580 if (this->mOutputCellAges) 00581 { 00582 cell_ages[cell] = cell_ptr->GetAge(); 00583 } 00584 if (this->mOutputCellCyclePhases) 00585 { 00586 cell_cycle_phases[cell] = cell_ptr->GetCellCycleModel()->GetCurrentCellCyclePhase(); 00587 } 00588 00589 cell ++; 00590 00592 } 00593 00594 //Cell IDs can be used to threshold out the empty lattice sites (which have ID=-1) 00595 mesh_writer.AddPointData("Cell ids", cell_ids); 00596 00597 if (this->mOutputCellProliferativeTypes) 00598 { 00599 mesh_writer.AddPointData("Cell types", cell_types); 00600 } 00601 if (this->mOutputCellAncestors) 00602 { 00603 mesh_writer.AddPointData("Ancestors", cell_ancestors); 00604 } 00605 if (this->mOutputCellMutationStates) 00606 { 00607 mesh_writer.AddPointData("Mutation states", cell_mutation_states); 00608 } 00609 if (this->mOutputCellAges) 00610 { 00611 mesh_writer.AddPointData("Ages", cell_ages); 00612 } 00613 if (this->mOutputCellCyclePhases) 00614 { 00615 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases); 00616 } 00617 00618 if (this->mOutputCellMutationStates) 00619 { 00620 mesh_writer.AddPointData("Mutation states", cell_mutation_states); 00621 mesh_writer.AddPointData("Cell labels", cell_labels); 00622 } 00623 00624 /* 00625 * The current VTK writer can only write things which inherit from AbstractTetrahedralMeshWriter. 00626 * For now, we do an explicit conversion to NodesOnlyMesh. This can be written to VTK then visualized as glyphs. 00627 */ 00628 NodesOnlyMesh<DIM> temp_mesh; 00629 temp_mesh.ConstructNodesWithoutMesh(nodes); 00630 mesh_writer.WriteFilesUsingMesh(temp_mesh); 00631 00632 *(this->mpVtkMetaFile) << " <DataSet timestep=\""; 00633 *(this->mpVtkMetaFile) << time.str(); 00634 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; 00635 *(this->mpVtkMetaFile) << time.str(); 00636 *(this->mpVtkMetaFile) << ".vtu\"/>\n"; 00637 00638 // Tidy up 00639 for (unsigned i=0; i<nodes.size(); i++) 00640 { 00641 delete nodes[i]; 00642 } 00643 #endif //CHASTE_VTK 00644 } 00645 00647 // Explicit instantiation 00649 00650 template class MultipleCaBasedCellPopulation<1>; 00651 template class MultipleCaBasedCellPopulation<2>; 00652 template class MultipleCaBasedCellPopulation<3>; 00653 00654 // Serialization for Boost >= 1.36 00655 #include "SerializationExportWrapperForCpp.hpp" 00656 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MultipleCaBasedCellPopulation)