36 #include "CaBasedCellPopulation.hpp"
38 #include <boost/scoped_array.hpp>
40 #include "RandomNumberGenerator.hpp"
41 #include "Warnings.hpp"
44 #include "VtkMeshWriter.hpp"
47 #include "CellAgesWriter.hpp"
48 #include "CellAncestorWriter.hpp"
49 #include "CellLocationIndexWriter.hpp"
50 #include "CellProliferativePhasesWriter.hpp"
51 #include "CellProliferativeTypesWriter.hpp"
54 #include "CellMutationStatesWriter.hpp"
57 #include "ExclusionCaBasedDivisionRule.hpp"
59 #include "NodesOnlyMesh.hpp"
62 template<
unsigned DIM>
68 template<
unsigned DIM>
70 std::vector<CellPtr>& rCells,
71 const std::vector<unsigned> locationIndices,
72 unsigned latticeCarryingCapacity,
76 mLatticeCarryingCapacity(latticeCarryingCapacity)
84 if (locationIndices.empty())
86 EXCEPTION(
"No location indices being passed. Specify where cells lie before creating the cell population.");
92 std::list<CellPtr>::iterator it = this->
mCells.begin();
93 for (
unsigned i=0; it != this->
mCells.end(); ++it, ++i)
95 assert(i<locationIndices.size());
98 EXCEPTION(
"One of the lattice sites has more cells than the carrying capacity. Check the initial cell locations.");
105 EXCEPTION(
"There is no validation for CaBasedCellPopulation.");
109 template<
unsigned DIM>
115 template<
unsigned DIM>
118 if (this->mDeleteMesh)
120 delete &this->mrMesh;
124 template<
unsigned DIM>
127 return mAvailableSpaces;
130 template<
unsigned DIM>
134 return (mAvailableSpaces[index] != 0);
137 template<
unsigned DIM>
143 template<
unsigned DIM>
149 template<
unsigned DIM>
152 return this->mrMesh.GetNode(index);
155 template<
unsigned DIM>
158 return this->mrMesh.GetNumNodes();
161 template<
unsigned DIM>
164 unsigned index = this->GetLocationIndexUsingCell(pCell);
167 std::set<unsigned> neighbour_indices;
168 for (std::set<unsigned>::iterator iter = candidates.begin();
169 iter != candidates.end();
172 if (!IsSiteAvailable(*iter, pCell))
174 neighbour_indices.insert(*iter);
178 return neighbour_indices;
181 template<
unsigned DIM>
184 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell))->rGetLocation();
187 template<
unsigned DIM>
190 return this->mrMesh.GetNode(this->GetLocationIndexUsingCell(pCell));
193 template<
unsigned DIM>
196 if (!IsSiteAvailable(index, pCell))
198 EXCEPTION(
"No available spaces at location index " << index <<
".");
201 mAvailableSpaces[index]--;
205 template<
unsigned DIM>
210 mAvailableSpaces[index]++;
212 assert(mAvailableSpaces[index] <= mLatticeCarryingCapacity);
215 template<
unsigned DIM>
218 return mpCaBasedDivisionRule->IsRoomToDivide(pCell, *
this);
221 template<
unsigned DIM>
224 unsigned daughter_node_index = mpCaBasedDivisionRule->CalculateDaughterNodeIndex(pNewCell,pParentCell,*
this);
227 this->mCells.push_back(pNewCell);
230 CellPtr p_created_cell = this->mCells.back();
231 AddCellUsingLocationIndex(daughter_node_index,p_created_cell);
233 return p_created_cell;
236 template<
unsigned DIM>
238 unsigned targetNodeIndex,
244 template<
unsigned DIM>
247 unsigned num_removed = 0;
249 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
250 cell_iter != this->mCells.end();
253 if ((*cell_iter)->IsDead())
256 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
258 RemoveCellUsingLocationIndex(node_index, (*cell_iter));
262 cell_iter = this->mCells.erase(cell_iter);
272 template<
unsigned DIM>
279 if (!(mUpdateRuleCollection.empty()))
283 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
284 cell_iter != this->mCells.end();
288 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
292 std::vector<double> neighbouring_node_propensities;
293 std::vector<unsigned> neighbouring_node_indices_vector;
295 if (!neighbouring_node_indices.empty())
297 unsigned num_neighbours = neighbouring_node_indices.size();
298 double probability_of_not_moving = 1.0;
300 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
301 iter != neighbouring_node_indices.end();
304 double probability_of_moving = 0.0;
306 neighbouring_node_indices_vector.push_back(*iter);
308 if (IsSiteAvailable(*iter, *cell_iter))
311 for (
typename std::vector<boost::shared_ptr<
AbstractCaUpdateRule<DIM> > >::iterator iterRule = mUpdateRuleCollection.begin();
312 iterRule != mUpdateRuleCollection.end();
315 probability_of_moving += (*iterRule)->EvaluateProbability(node_index, *iter, *
this, dt, 1, *cell_iter);
316 if (probability_of_moving < 0)
318 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");
321 if (probability_of_moving > 1)
323 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");
327 probability_of_not_moving -= probability_of_moving;
328 neighbouring_node_propensities.push_back(probability_of_moving);
332 neighbouring_node_propensities.push_back(0.0);
335 if (probability_of_not_moving < 0)
337 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");
342 double random_number = p_gen->
ranf();
344 double total_probability = 0.0;
345 for (
unsigned counter=0; counter<num_neighbours; counter++)
347 total_probability += neighbouring_node_propensities[counter];
348 if (total_probability >= random_number)
351 unsigned chosen_neighbour_location_index = neighbouring_node_indices_vector[counter];
352 this->MoveCellInLocationMap((*cell_iter), node_index, chosen_neighbour_location_index);
372 if (!(mSwitchingUpdateRuleCollection.empty()))
374 assert(mLatticeCarryingCapacity == 1);
377 unsigned num_nodes = this->mrMesh.GetNumNodes();
380 if (this->mIterateRandomlyOverUpdateRuleCollection)
383 p_gen->
Shuffle(mSwitchingUpdateRuleCollection);
386 for (
unsigned i=0; i<num_nodes; i++)
390 if (this->mUpdateNodesInRandomOrder)
392 node_index = p_gen->
randMod(num_nodes);
397 node_index = i%num_nodes;
403 unsigned neighbour_location_index;
405 if (!neighbouring_node_indices.empty())
407 unsigned num_neighbours = neighbouring_node_indices.size();
408 unsigned chosen_neighbour = p_gen->
randMod(num_neighbours);
410 std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
411 for (
unsigned j=0; j<chosen_neighbour; j++)
415 neighbour_location_index = *neighbour_iter;
417 bool is_cell_on_node_index = mAvailableSpaces[node_index] == 0 ?
true :
false;
418 bool is_cell_on_neighbour_location_index = mAvailableSpaces[neighbour_location_index] == 0 ?
true :
false;
420 if (is_cell_on_node_index || is_cell_on_neighbour_location_index)
422 double probability_of_switch = 0.0;
426 iter != mSwitchingUpdateRuleCollection.end();
429 probability_of_switch += (*iter)->EvaluateSwitchingProbability(node_index, neighbour_location_index, *
this, dt, 1);
431 assert(probability_of_switch>=0);
432 assert(probability_of_switch<=1);
435 double random_number = p_gen->
ranf();
437 if (random_number < probability_of_switch)
439 if (is_cell_on_node_index && is_cell_on_neighbour_location_index)
442 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
443 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
446 RemoveCellUsingLocationIndex(node_index, p_cell);
447 RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
450 AddCellUsingLocationIndex(node_index, p_neighbour_cell);
451 AddCellUsingLocationIndex(neighbour_location_index, p_cell);
453 else if (is_cell_on_node_index && !is_cell_on_neighbour_location_index)
456 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
457 RemoveCellUsingLocationIndex(node_index, p_cell);
458 AddCellUsingLocationIndex(neighbour_location_index, p_cell);
460 else if (!is_cell_on_node_index && is_cell_on_neighbour_location_index)
463 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(neighbour_location_index);
464 RemoveCellUsingLocationIndex(neighbour_location_index, p_neighbour_cell);
465 AddCellUsingLocationIndex(node_index, p_neighbour_cell);
479 template<
unsigned DIM>
485 template<
unsigned DIM>
490 template<
unsigned DIM>
493 pPopulationWriter->Visit(
this);
496 template<
unsigned DIM>
499 pPopulationCountWriter->Visit(
this);
502 template<
unsigned DIM>
505 pCellWriter->VisitCell(pCell,
this);
508 template<
unsigned DIM>
511 if (this->mOutputResultsForChasteVisualizer)
513 if (!this->
template HasWriter<CellLocationIndexWriter>())
515 this->
template AddCellWriter<CellLocationIndexWriter>();
522 template<
unsigned DIM>
525 double cell_volume = 1.0;
529 template<
unsigned DIM>
532 double width = this->mrMesh.GetWidth(rDimension);
536 template<
unsigned DIM>
539 mUpdateRuleCollection.push_back(pUpdateRule);
542 template<
unsigned DIM>
545 mUpdateRuleCollection.clear();
548 template<
unsigned DIM>
551 return mUpdateRuleCollection;
554 template<
unsigned DIM>
557 mSwitchingUpdateRuleCollection.push_back(pUpdateRule);
560 template<
unsigned DIM>
563 mSwitchingUpdateRuleCollection.clear();
566 template<
unsigned DIM>
569 return mSwitchingUpdateRuleCollection;
572 template<
unsigned DIM>
575 return mpCaBasedDivisionRule;
578 template<
unsigned DIM>
581 mpCaBasedDivisionRule = pCaBasedDivisionRule;
584 template<
unsigned DIM>
588 *rParamsFile <<
"\t\t<CaBasedDivisionRule>\n";
589 mpCaBasedDivisionRule->OutputCellCaBasedDivisionRuleInfo(rParamsFile);
590 *rParamsFile <<
"\t\t</CaBasedDivisionRule>\n";
596 template<
unsigned DIM>
602 std::stringstream time;
603 time << num_timesteps;
606 unsigned num_cells = this->GetNumAllCells();
609 unsigned num_cell_data_items = 0u;
610 std::vector<std::string> cell_data_names;
613 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
614 cell_data_names = this->Begin()->GetCellData()->GetKeys();
616 std::vector<std::vector<double> > cell_data;
617 for (
unsigned var=0; var<num_cell_data_items; var++)
619 std::vector<double> cell_data_var(num_cells);
620 cell_data.push_back(cell_data_var);
628 boost::scoped_array<unsigned> number_of_cells_at_site(
new unsigned[num_sites]);
629 for (
unsigned i=0; i<num_sites; i++)
631 number_of_cells_at_site[i] = 0;
635 std::vector<Node<DIM>*> nodes;
636 unsigned node_index = 0;
637 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
638 cell_iter != this->mCells.end();
642 unsigned location_index = this->GetLocationIndexUsingCell(*cell_iter);
643 number_of_cells_at_site[location_index]++;
644 assert(number_of_cells_at_site[location_index] <= mLatticeCarryingCapacity);
647 c_vector<double, DIM> coords;
648 coords = this->mrMesh.GetNode(location_index)->rGetLocation();
651 if (mLatticeCarryingCapacity > 1)
653 c_vector<double, DIM> offset;
657 double angle = (
double)number_of_cells_at_site[location_index]*2.0*M_PI/(
double)mLatticeCarryingCapacity;
658 offset[0] = 0.2*sin(angle);
659 offset[1] = 0.2*cos(angle);
664 for (
unsigned i=0; i<DIM; i++)
666 offset[i] = p_gen->
ranf();
670 for (
unsigned i=0; i<DIM; i++)
672 coords[i] += offset[i];
676 nodes.push_back(
new Node<DIM>(node_index, coords,
false));
682 cell_writer_iter != this->mCellWriters.end();
687 std::vector<double> vtk_cell_data(num_cells, -1.0);
690 unsigned cell_index = 0;
691 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
692 cell_iter != this->mCells.end();
696 vtk_cell_data[cell_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter,
this);
700 mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
704 unsigned cell_index = 0;
706 cell_iter != this->End();
709 for (
unsigned var=0; var<num_cell_data_items; var++)
711 cell_data[var][cell_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
715 for (
unsigned var=0; var<num_cell_data_items; var++)
717 mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
729 double volume = this->mrMesh.
GetWidth(0);
730 for(
unsigned idx=1; idx<DIM; idx++)
732 volume *= this->mrMesh.GetWidth(idx);
736 if(this->mrMesh.GetNumNodes() >0 && volume > 0.0)
738 spacing = std::pow(volume /
double(this->mrMesh.GetNumNodes()), 1.0/
double(DIM));
746 mesh_writer.WriteFilesUsingMesh(temp_mesh);
748 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
749 *(this->mpVtkMetaFile) << num_timesteps;
750 *(this->mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
751 *(this->mpVtkMetaFile) << num_timesteps;
752 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
755 for (
unsigned i=0; i<nodes.size(); i++)
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > GetCaBasedDivisionRule()
std::vector< unsigned > mAvailableSpaces
unsigned randMod(unsigned base)
std::vector< unsigned > & rGetAvailableSpaces()
void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual double EvaluateDivisionPropensity(unsigned currentNodeIndex, unsigned targetNodeIndex, CellPtr pCell)
PottsMesh< DIM > & rGetMesh()
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
Node< DIM > * GetNode(unsigned index)
#define EXCEPTION(message)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
static SimulationTime * Instance()
virtual bool IsSiteAvailable(unsigned index, CellPtr pCell)
virtual unsigned GetNumNodes()
boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > mpCaBasedDivisionRule
virtual unsigned GetNumNodes() const
unsigned GetTimeStepsElapsed() const
const std::vector< boost::shared_ptr< AbstractCaUpdateRule< DIM > > > & rGetUpdateRuleCollection() const
std::set< unsigned > GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual ~CaBasedCellPopulation()
CaBasedCellPopulation(PottsMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices, unsigned latticeCarryingCapacity=1u, bool deleteMesh=false, bool validate=false)
void Shuffle(std::vector< boost::shared_ptr< T > > &rValues)
bool IsRoomToDivide(CellPtr pCell)
void SetCaBasedDivisionRule(boost::shared_ptr< AbstractCaBasedDivisionRule< DIM > > pCaBasedDivisionRule)
void RemoveAllSwitchingUpdateRules()
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
double GetWidth(const unsigned &rDimension) const
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
void UpdateCellLocations(double dt)
void Update(bool hasHadBirthsOrDeaths=true)
const std::vector< boost::shared_ptr< AbstractCaSwitchingUpdateRule< DIM > > > & rGetSwitchingUpdateRuleCollection() const
void AddSwitchingUpdateRule(boost::shared_ptr< AbstractCaSwitchingUpdateRule< DIM > > pUpdateRule)
static RandomNumberGenerator * Instance()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
std::list< CellPtr > mCells
void RemoveAllUpdateRules()
void ConstructNodesWithoutMesh(const std::vector< Node< SPACE_DIM > * > &rNodes, double maxInteractionDistance)
void AddUpdateRule(boost::shared_ptr< AbstractCaUpdateRule< DIM > > pUpdateRule)
Node< DIM > * GetNodeCorrespondingToCell(CellPtr pCell)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
double GetWidth(const unsigned &rDimension)
unsigned RemoveDeadCells()
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
double GetVolumeOfCell(CellPtr pCell)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
AbstractMesh< ELEMENT_DIM, ELEMENT_DIM > & mrMesh
CellPtr AddCell(CellPtr pNewCell, const c_vector< double, DIM > &rCellDivisionVector, CellPtr pParentCell=CellPtr())
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)