Chaste Release::3.1
MultipleCaBasedCellPopulation.cpp
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)