Chaste Commit::baa90ac2819b962188b7562f2326be23c47859a7
AbstractCellPopulation.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include <algorithm>
37#include <functional>
38
39#include "AbstractCellPopulation.hpp"
40#include "AbstractPhaseBasedCellCycleModel.hpp"
41#include "SmartPointers.hpp"
42#include "CellAncestor.hpp"
43#include "ApoptoticCellProperty.hpp"
44
45// Cell writers
46#include "BoundaryNodeWriter.hpp"
47#include "CellProliferativeTypesWriter.hpp"
48#include "LegacyCellProliferativeTypesWriter.hpp"
49#include "CellRemovalLocationsWriter.hpp"
50
51// Cell population writers
52#include "CellMutationStatesCountWriter.hpp"
53#include "CellProliferativePhasesCountWriter.hpp"
54#include "CellProliferativeTypesCountWriter.hpp"
55#include "NodeLocationWriter.hpp"
56
57// These #includes are needed for SetDefaultCellMutationStateAndProliferativeTypeOrdering()
58#include "WildTypeCellMutationState.hpp"
59#include "ApcOneHitCellMutationState.hpp"
60#include "ApcTwoHitCellMutationState.hpp"
61#include "BetaCateninOneHitCellMutationState.hpp"
62#include "DefaultCellProliferativeType.hpp"
63#include "StemCellProliferativeType.hpp"
64#include "TransitCellProliferativeType.hpp"
65#include "DifferentiatedCellProliferativeType.hpp"
66
67template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
69 std::vector<CellPtr>& rCells,
70 const std::vector<unsigned> locationIndices)
71 : mrMesh(rMesh),
72 mCells(rCells.begin(), rCells.end()),
73 mCentroid(zero_vector<double>(SPACE_DIM)),
74 mpCellPropertyRegistry(CellPropertyRegistry::Instance()->TakeOwnership()),
75 mOutputResultsForChasteVisualizer(true)
76{
77 /*
78 * To avoid double-counting problems, clear the passed-in cells vector.
79 * We force a reallocation of memory so that subsequent usage of the
80 * vector is more likely to give an error.
81 */
82 std::vector<CellPtr>().swap(rCells);
83
84 // There must be a one-one correspondence between cells and location indices
85 if (!locationIndices.empty())
86 {
87 if (mCells.size() != locationIndices.size())
88 {
89 EXCEPTION("There is not a one-one correspondence between cells and location indices");
90 }
91 }
92
93 // Set up the map between location indices and cells
94 mLocationCellMap.clear();
95 mCellLocationMap.clear();
96
97 std::list<CellPtr>::iterator it = mCells.begin();
98 for (unsigned i=0; it != mCells.end(); ++it, ++i)
99 {
100 // Give each cell a pointer to the property registry (we have taken ownership in this constructor)
101 (*it)->rGetCellPropertyCollection().SetCellPropertyRegistry(mpCellPropertyRegistry.get());
102 }
103
104 // Clear stored divisions and removals information
107}
108
109template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
114
115template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
117{
118}
119
120template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
122{
123 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
124 cell_iter!=this->End();
125 ++cell_iter)
126 {
127 cell_iter->InitialiseCellCycleModel();
128 cell_iter->InitialiseSrnModel();
129 }
130}
131
132template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
133void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetDataOnAllCells(const std::string& rDataName, double dataValue)
134{
135 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
136 cell_iter!=this->End();
137 ++cell_iter)
138 {
139 cell_iter->GetCellData()->SetItem(rDataName, dataValue);
140 }
141}
142
143template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
148
149template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
151{
152 return mCells;
153}
154
155template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
157{
158 unsigned counter = 0;
159 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
160 cell_iter!=this->End();
161 ++cell_iter)
162 {
163 counter++;
164 }
165 return counter;
166}
167
168template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
170{
171 return mCells.size();
172}
173
174template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
176{
177 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
178 {
179 MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()]));
180 cell_iter->SetAncestor(p_cell_ancestor);
181 }
182}
183
184template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
186{
187 std::set<unsigned> remaining_ancestors;
188 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
189 {
190 remaining_ancestors.insert(cell_iter->GetAncestor());
191 }
192 return remaining_ancestors;
193}
194
195template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
197{
198 std::vector<unsigned> mutation_state_count;
199 const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
200 = mpCellPropertyRegistry->rGetAllCellProperties();
201
202 // Calculate mutation states count
203 for (unsigned i=0; i<r_cell_properties.size(); i++)
204 {
205 if (r_cell_properties[i]->IsSubType<AbstractCellMutationState>())
206 {
207 mutation_state_count.push_back(r_cell_properties[i]->GetCellCount());
209 }
210
211 // Reduce results onto all processes
213 {
214 // Make sure the vector on each process has the same size
215 unsigned local_size = mutation_state_count.size();
216 unsigned global_size;
217 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
218 assert(local_size == global_size);
219
220 std::vector<unsigned> mutation_counts(global_size);
221 MPI_Allreduce(&mutation_state_count[0], &mutation_counts[0], mutation_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
222
223 mutation_state_count = mutation_counts;
224 }
225
226 return mutation_state_count;
227}
228
229template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
231{
232 std::vector<unsigned> proliferative_type_count;
233 const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
234 = mpCellPropertyRegistry->rGetAllCellProperties();
236 // Calculate proliferative types count
237 for (unsigned i=0; i<r_cell_properties.size(); i++)
238 {
239 if (r_cell_properties[i]->IsSubType<AbstractCellProliferativeType>())
240 {
241 proliferative_type_count.push_back(r_cell_properties[i]->GetCellCount());
243 }
244
245 // Reduce results onto all processes
248 // Make sure the vector on each process has the same size
249 unsigned local_size = proliferative_type_count.size();
250 unsigned global_size;
251
252 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
253 assert(local_size == global_size);
254
255 std::vector<unsigned> total_types_counts(global_size);
256 MPI_Allreduce(&proliferative_type_count[0], &total_types_counts[0], total_types_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
257
258 proliferative_type_count = total_types_counts;
259 }
260
261 return proliferative_type_count;
262}
263
264template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
266{
267 std::vector<unsigned> cell_cycle_phase_count(5);
268 for (unsigned i=0; i<5; i++)
269 {
270 cell_cycle_phase_count[i] = 0;
271 }
272
273 /*
274 * Note that in parallel with a poor partition a process could end up with zero cells
275 * in which case the calculation should be skipped since `this->Begin()` is not defined.
276 */
277 if (GetNumAllCells() > 0u)
278 {
279 if (dynamic_cast<AbstractPhaseBasedCellCycleModel*>((*(this->Begin()))->GetCellCycleModel()) == nullptr)
280 {
281 EXCEPTION("You are trying to record the cell cycle phase of cells with a non phase based cell cycle model.");
282 }
283
284 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
285 cell_iter != this->End();
286 ++cell_iter)
287 {
288 switch (static_cast<AbstractPhaseBasedCellCycleModel*>((*cell_iter)->GetCellCycleModel())->GetCurrentCellCyclePhase())
289 {
290 case G_ZERO_PHASE:
291 cell_cycle_phase_count[0]++;
292 break;
293 case G_ONE_PHASE:
294 cell_cycle_phase_count[1]++;
295 break;
296 case S_PHASE:
297 cell_cycle_phase_count[2]++;
298 break;
299 case G_TWO_PHASE:
300 cell_cycle_phase_count[3]++;
301 break;
302 case M_PHASE:
303 cell_cycle_phase_count[4]++;
304 break;
305 default:
307 }
308 }
309 }
310
311 // Reduce results onto all processes
313 {
314 std::vector<unsigned> phase_counts(cell_cycle_phase_count.size(), 0u);
315 MPI_Allreduce(&cell_cycle_phase_count[0], &phase_counts[0], phase_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
316
317 cell_cycle_phase_count = phase_counts;
318 }
319
320 return cell_cycle_phase_count;
321}
322
323template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
325{
326 // Get the set of pointers to cells corresponding to this location index
327 std::set<CellPtr> cells = mLocationCellMap[index];
328
329 // If there is only one cell attached return the cell. Note currently only one cell per index.
330 if (cells.size() == 1)
331 {
332 return *(cells.begin());
333 }
334 if (cells.empty())
335 {
336 EXCEPTION("Location index input argument does not correspond to a Cell");
337 }
338 else
339 {
340 EXCEPTION("Multiple cells are attached to a single location index.");
341 }
342}
343
344template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
346{
347 // Return the set of pointers to cells corresponding to this location index, note the set may be empty.
348 return mLocationCellMap[index];
349}
350
351template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
353{
354 // Get the set of pointers to cells corresponding to this location index
355 std::set<CellPtr> cells = mLocationCellMap[index];
356
357 // Return whether there is a cell attached to the location index
358 return !(cells.empty());
359}
360
361template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
365
366template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
368{
369 // Clear the maps
370 mLocationCellMap[index].clear();
371 mCellLocationMap.erase(pCell.get());
372
373 // Replace with new cell
374 mLocationCellMap[index].insert(pCell);
375
376 // Do other half of the map
377 mCellLocationMap[pCell.get()] = index;
378}
379
380template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
382{
383 mLocationCellMap[index].insert(pCell);
384 mCellLocationMap[pCell.get()] = index;
385}
386
387template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
389{
390 std::set<CellPtr>::iterator cell_iter = mLocationCellMap[index].find(pCell);
391
392 if (cell_iter == mLocationCellMap[index].end())
393 {
394 EXCEPTION("Tried to remove a cell which is not attached to the given location index");
395 }
396 else
397 {
398 mLocationCellMap[index].erase(cell_iter);
399 mCellLocationMap.erase(pCell.get());
400 }
401}
402
403template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
404void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
405{
406 // Remove the cell from its current location
407 RemoveCellUsingLocationIndex(old_index, pCell);
408
409 // Add it to the new location
410 AddCellUsingLocationIndex(new_index, pCell);
411}
412
413template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
415{
416 // Check the cell is in the map
417 assert(this->mCellLocationMap.find(pCell.get()) != this->mCellLocationMap.end());
418
419 return mCellLocationMap[pCell.get()];
420}
421
422template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
424{
425 return mpCellPropertyRegistry;
426}
427
428template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
430{
431 boost::shared_ptr<CellPropertyRegistry> p_registry = GetCellPropertyRegistry();
432 if (!p_registry->HasOrderingBeenSpecified())
433 {
434 std::vector<boost::shared_ptr<AbstractCellProperty> > mutations_and_proliferative_types;
435 mutations_and_proliferative_types.push_back(p_registry->Get<WildTypeCellMutationState>());
436 mutations_and_proliferative_types.push_back(p_registry->Get<ApcOneHitCellMutationState>());
437 mutations_and_proliferative_types.push_back(p_registry->Get<ApcTwoHitCellMutationState>());
438 mutations_and_proliferative_types.push_back(p_registry->Get<BetaCateninOneHitCellMutationState>());
439 mutations_and_proliferative_types.push_back(p_registry->Get<StemCellProliferativeType>());
440 mutations_and_proliferative_types.push_back(p_registry->Get<TransitCellProliferativeType>());
441 mutations_and_proliferative_types.push_back(p_registry->Get<DifferentiatedCellProliferativeType>());
442
443 // Parallel process with no cells won't have the default property, so add it in
444 mutations_and_proliferative_types.push_back(p_registry->Get<DefaultCellProliferativeType>());
445 p_registry->SpecifyOrdering(mutations_and_proliferative_types);
446 }
447}
448
449/*
450 * We exclude the following from coverage, as these methods are implemented elsewhere and tested accordingly
451 */
452// LCOV_EXCL_START
453template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
454std::set<std::pair<unsigned, unsigned>> AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringEdgeIndices(CellPtr cell, unsigned pEdgeLocalIndex)
455{
456 return std::set<std::pair<unsigned, unsigned>>();
457}
458// LCOV_EXCL_STOP
460template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
462{
463 mCentroid = zero_vector<double>(SPACE_DIM);
464 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
465 cell_iter != this->End();
466 ++cell_iter)
468 mCentroid += GetLocationOfCellCentre(*cell_iter);
469 }
470 mCentroid /= this->GetNumRealCells();
471
472 return mCentroid;
473}
474
475template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
480template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
482{
483 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
484 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
485 {
486 p_cell_writer->CloseFile();
487 }
488
490 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
491 {
492 p_pop_writer->CloseFile();
493 }
494}
495
496template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
498{
500 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
501 {
502 p_cell_writer->CloseFile();
503 }
504
506 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
507 {
508 p_pop_writer->CloseFile();
509 }
510
511#ifdef CHASTE_VTK
512 *mpVtkMetaFile << " </Collection>\n";
513 *mpVtkMetaFile << "</VTKFile>\n";
514 mpVtkMetaFile->close();
515#endif //CHASTE_VTK
516}
517
518template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
520{
521#ifdef CHASTE_VTK
522 mpVtkMetaFile = rOutputFileHandler.OpenOutputFile("results.pvd");
523 *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
524 *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
525 *mpVtkMetaFile << " <Collection>\n";
526#endif //CHASTE_VTK
528 if (mOutputResultsForChasteVisualizer)
529 {
530 if (!HasWriter<NodeLocationWriter>())
531 {
532 AddPopulationWriter<NodeLocationWriter>();
533 }
534 if (!HasWriter<BoundaryNodeWriter>())
535 {
536 AddPopulationWriter<BoundaryNodeWriter>();
537 }
538 if (!HasWriter<CellProliferativeTypesWriter>())
539 {
540 AddCellWriter<CellProliferativeTypesWriter>();
541 }
542 if (!HasWriter<LegacyCellProliferativeTypesWriter>())
543 {
544 AddCellWriter<LegacyCellProliferativeTypesWriter>();
545 }
546 }
548 // Open output files for any cell writers
549 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
550 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
551 {
552 p_cell_writer->OpenOutputFile(rOutputFileHandler);
553 }
554
555 // Open output files and write headers for any population writers
557 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
559 p_pop_writer->OpenOutputFile(rOutputFileHandler);
560 p_pop_writer->WriteHeader(this);
561 }
562
563 // Open output files and write headers for any population count writers
565 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
566 {
567 p_count_writer->OpenOutputFile(rOutputFileHandler);
568 p_count_writer->WriteHeader(this);
569 }
570
571 // Open output files and write headers for any population event writers
573 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
574 {
575 p_event_writer->OpenOutputFile(rOutputFileHandler);
576 p_event_writer->WriteHeader(this);
577 }
578}
579
580template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
582{
583 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
585 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
586 {
587 p_cell_writer->OpenOutputFileForAppend(rOutputFileHandler);
588 }
589 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
590 {
591 p_pop_writer->OpenOutputFileForAppend(rOutputFileHandler);
592 }
593}
594
595template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
597{
598 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
600 OutputFileHandler output_file_handler(rDirectory, false);
601
602 if (!(mCellWriters.empty() && mCellPopulationWriters.empty() && mCellPopulationCountWriters.empty()))
603 {
604 // An ordering must be specified for cell mutation states and cell proliferative types
605 SetDefaultCellMutationStateAndProliferativeTypeOrdering();
606
609 OpenRoundRobinWritersFilesForAppend(output_file_handler);
610
611 // The master process writes time stamps
614 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
615 {
616 p_cell_writer->WriteTimeStamp();
617 }
618 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
619 {
620 p_pop_writer->WriteTimeStamp();
621 }
622 }
623
624 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator pop_writer_iter = mCellPopulationWriters.begin();
625 pop_writer_iter != mCellPopulationWriters.end();
626 ++pop_writer_iter)
627 {
628 AcceptPopulationWriter(*pop_writer_iter);
629 }
630
631 AcceptCellWritersAcrossPopulation();
632
633 // The top-most process adds a newline
635 {
636 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
637 {
638 p_cell_writer->WriteNewline();
639 }
640 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
642 p_pop_writer->WriteNewline();
643 }
644 }
645 CloseRoundRobinWritersFiles();
646 }
649 // Outside the round robin, deal with population count writers
651
653 {
654 // Open mCellPopulationCountWriters in append mode for writing, and write time stamps
655 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
656 {
657 p_count_writer->OpenOutputFileForAppend(output_file_handler);
658 p_count_writer->WriteTimeStamp();
659 }
660 }
661 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator count_writer_iter = mCellPopulationCountWriters.begin();
662 count_writer_iter != mCellPopulationCountWriters.end();
663 ++count_writer_iter)
664 {
665 AcceptPopulationCountWriter(*count_writer_iter);
666 }
667
669 {
670 // Add a newline and close any output files
671 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
672 {
673 p_count_writer->WriteNewline();
674 p_count_writer->CloseFile();
675 }
676 }
677
678
679 // Outside the round robin, deal with population event writers
681
683 {
684 // Open mCellPopulationCountWriters in append mode for writing
685 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
686 {
687 p_event_writer->OpenOutputFileForAppend(output_file_handler);
688 }
689 }
690 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationEventWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator event_writer_iter = mCellPopulationEventWriters.begin();
691 event_writer_iter != mCellPopulationEventWriters.end();
692 ++event_writer_iter)
693 {
694 AcceptPopulationEventWriter(*event_writer_iter);
695 }
698 {
699 // Close any output files
700 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
701 {
702 p_event_writer->CloseFile();
703 }
704 }
706
707 // VTK can only be written in 2 or 3 dimensions
708 if (SPACE_DIM > 1)
709 {
710 WriteVtkResultsToFile(rDirectory);
711 }
712}
713
714template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
716{
717 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
718 cell_iter != this->End();
719 ++cell_iter)
720 {
721 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = mCellWriters.begin();
722 cell_writer_iter != mCellWriters.end();
723 ++cell_writer_iter)
725 AcceptCellWriter(*cell_writer_iter, *cell_iter);
726 }
727 }
728}
730template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
732{
733 std::string cell_population_type = GetIdentifier();
734
735 *rParamsFile << "\t<" << cell_population_type << ">\n";
736 OutputCellPopulationParameters(rParamsFile);
737 *rParamsFile << "\t</" << cell_population_type << ">\n";
738 *rParamsFile << "\n";
739 *rParamsFile << "\t<CellCycleModels>\n";
740
747 std::set<std::string> unique_cell_cycle_models;
748 std::vector<CellPtr> first_cell_with_unique_CCM;
749 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
750 cell_iter != this->End();
751 ++cell_iter)
752 {
753 std::string identifier = cell_iter->GetCellCycleModel()->GetIdentifier();
754 if (unique_cell_cycle_models.count(identifier) == 0)
755 {
756 unique_cell_cycle_models.insert(identifier);
757 first_cell_with_unique_CCM.push_back((*cell_iter));
758 }
759 }
761 // Loop over unique cell-cycle models
762 for (unsigned i=0; i<first_cell_with_unique_CCM.size(); i++)
763 {
764 // Output cell-cycle model details
765 first_cell_with_unique_CCM[i]->GetCellCycleModel()->OutputCellCycleModelInfo(rParamsFile);
766 }
767 *rParamsFile << "\t</CellCycleModels>\n";
768
769 *rParamsFile << "\n";
770 *rParamsFile << "\t<SrnModels>\n";
771
778 std::set<std::string> unique_srn_models;
779 std::vector<CellPtr> first_cell_with_unique_SRN;
780 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
781 cell_iter != this->End();
782 ++cell_iter)
783 {
784 std::string identifier = cell_iter->GetSrnModel()->GetIdentifier();
785 if (unique_srn_models.count(identifier) == 0)
787 unique_srn_models.insert(identifier);
788 first_cell_with_unique_SRN.push_back((*cell_iter));
789 }
790 }
792 // Loop over unique SRN models
793 for (unsigned i=0; i<first_cell_with_unique_SRN.size(); i++)
794 {
795 // Output SRN model details
796 first_cell_with_unique_SRN[i]->GetSrnModel()->OutputSrnModelInfo(rParamsFile);
797 }
798
799 *rParamsFile << "\t</SrnModels>\n";
800}
801
802template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
804{
805 *rParamsFile << "\t\t<OutputResultsForChasteVisualizer>" << mOutputResultsForChasteVisualizer << "</OutputResultsForChasteVisualizer>\n";
806}
807
808template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
812
813template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
815{
816 return mOutputResultsForChasteVisualizer;
817}
818
819template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
821{
822 mOutputResultsForChasteVisualizer = outputResultsForChasteVisualizer;
823}
824
825template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
827{
828 return mDivisionsInformation;
829}
830template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
832{
833 mDivisionsInformation.push_back(divisionInformation);
834}
835
836template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
838{
839 mDivisionsInformation.clear();
840}
841
842template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
844{
845 return mRemovalsInformation;
846}
847
848template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
850{
851 mRemovalsInformation.push_back(removalInformation);
852}
853
854template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
856{
857 mRemovalsInformation.clear();
858}
859
860template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
862{
863 //If necessary store the information about the cell removal
864 c_vector<double, SPACE_DIM> cell_location = GetLocationOfCellCentre(pCell);
865 if (HasWriter<CellRemovalLocationsWriter>())
866 {
867 std::stringstream removal_info;
868 removal_info << SimulationTime::Instance()->GetTime() << "\t";
869 for (unsigned i = 0; i < SPACE_DIM; i++)
870 {
871 removal_info << cell_location[i] << "\t";
872 }
873 removal_info << "\t" << pCell->GetAge() << "\t" << pCell->GetCellId() << "\t" << killerInfo << "\t";
874
875 AddRemovalInformation(removal_info.str());
876 }
877}
878
879template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
880void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::KillCell(CellPtr pCell, std::string killerInfo)
881{
882 //If necessary store the information about the cell removal
883 GenerateRemovalInformation(pCell, killerInfo);
884
885 //Mark cell as dead
886 pCell->Kill();
887}
888
889template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
891{
892 //If necessary store the information about the cell removal
893 GenerateRemovalInformation(pCell, killerInfo);
894
895 //Mark cell as Apoptotic
896 pCell->StartApoptosis();
897}
898
899template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
901{
902 return true;
903}
904
905template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
907{
908 // Compute the centre of mass of the cell population
909 c_vector<double,SPACE_DIM> centre = GetCentroidOfCellPopulation();
910
911 // Loop over cells and find the maximum distance from the centre of mass in each dimension
912 c_vector<double,SPACE_DIM> max_distance_from_centre = zero_vector<double>(SPACE_DIM);
913 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
914 cell_iter != this->End();
915 ++cell_iter)
916 {
917 c_vector<double,SPACE_DIM> cell_location = GetLocationOfCellCentre(*cell_iter);
918
919 // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
920 c_vector<double,SPACE_DIM> displacement;
921 displacement = centre - cell_location;
922
923 for (unsigned i=0; i<SPACE_DIM; i++)
924 {
925 if (displacement[i] > max_distance_from_centre[i])
926 {
927 max_distance_from_centre[i] = displacement[i];
928 }
929 }
930 }
931
932 return max_distance_from_centre;
933}
934
935template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
936std::pair<unsigned,unsigned> AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOrderedPair(unsigned index1, unsigned index2)
938 assert(index1 != index2);
939
940 std::pair<unsigned, unsigned> ordered_pair;
941 if (index1 < index2)
942 {
943 ordered_pair.first = index1;
944 ordered_pair.second = index2;
945 }
946 else
947 {
948 ordered_pair.first = index2;
949 ordered_pair.second = index1;
950 }
951 return ordered_pair;
952}
953
954template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
956{
957 bool non_apoptotic_cell_present = false;
958
959 if (IsCellAttachedToLocationIndex(pdeNodeIndex))
961 non_apoptotic_cell_present = !(GetCellUsingLocationIndex(pdeNodeIndex)->template HasCellProperty<ApoptoticCellProperty>());
962 }
963
964 return non_apoptotic_cell_present;
965}
966
967
968// Explicit instantiation
969template class AbstractCellPopulation<1,1>;
970template class AbstractCellPopulation<1,2>;
971template class AbstractCellPopulation<2,2>;
972template class AbstractCellPopulation<1,3>;
973template class AbstractCellPopulation<2,3>;
974template class AbstractCellPopulation<3,3>;
#define EXCEPTION(message)
#define NEVER_REACHED
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
virtual void OpenOutputFile(OutputFileHandler &rOutputFileHandler)
void OpenOutputFileForAppend(OutputFileHandler &rOutputFileHandler)
boost::shared_ptr< CellPropertyRegistry > mpCellPropertyRegistry
std::vector< std::string > GetDivisionsInformation()
void OpenRoundRobinWritersFilesForAppend(OutputFileHandler &rOutputFileHandler)
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::vector< std::string > GetRemovalsInformation()
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
std::vector< unsigned > GetCellMutationStateCount()
std::list< CellPtr > & rGetCells()
void SetDataOnAllCells(const std::string &rDataName, double dataValue)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
virtual bool IsCellAttachedToLocationIndex(unsigned index)
virtual bool IsRoomToDivide(CellPtr pCell)
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
unsigned GetLocationIndexUsingCell(CellPtr pCell)
void SetOutputResultsForChasteVisualizer(bool outputResultsForChasteVisualizer)
virtual void WriteResultsToFiles(const std::string &rDirectory)
std::set< CellPtr > GetCellsUsingLocationIndex(unsigned index)
std::set< unsigned > GetCellAncestors()
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)=0
virtual std::set< std::pair< unsigned, unsigned > > GetNeighbouringEdgeIndices(CellPtr pCell, unsigned pEdgeIndex)
virtual void SimulationSetupHook(AbstractCellBasedSimulation< ELEMENT_DIM, SPACE_DIM > *pSimulation)
boost::shared_ptr< CellPropertyRegistry > GetCellPropertyRegistry()
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
void GenerateRemovalInformation(CellPtr pCell, std::string killerInfo)
std::map< Cell *, unsigned > mCellLocationMap
void OutputCellPopulationInfo(out_stream &rParamsFile)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
std::vector< unsigned > GetCellCyclePhaseCount()
AbstractCellPopulation(AbstractMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & rGetMesh()
void StartApoptosisOnCell(CellPtr pCell, std::string killerInfo)
c_vector< double, SPACE_DIM > GetCentroidOfCellPopulation()
void KillCell(CellPtr pCell, std::string killerInfo)
std::vector< unsigned > GetCellProliferativeTypeCount()
void AddRemovalInformation(std::string removalInformation)
void SetDefaultCellMutationStateAndProliferativeTypeOrdering()
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
void MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
c_vector< double, SPACE_DIM > GetSizeOfCellPopulation()
void AddDivisionInformation(std::string divisionInformation)
virtual void AcceptCellWritersAcrossPopulation()
virtual void RemoveCellUsingLocationIndex(unsigned index, CellPtr pCell)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static MPI_Comm GetWorld()
static bool AmMaster()
static bool AmTopMost()
static bool IsParallel()
static void EndRoundRobin()
static void BeginRoundRobin()
double GetTime() const
static SimulationTime * Instance()