Chaste Commit::f2ff7ee04e70ac9d06c57344df8d017dbb12b97b
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 <boost/bind.hpp>
37
38#include <algorithm>
39#include <functional>
40
41#include "AbstractCellPopulation.hpp"
42#include "AbstractPhaseBasedCellCycleModel.hpp"
43#include "SmartPointers.hpp"
44#include "CellAncestor.hpp"
45#include "ApoptoticCellProperty.hpp"
46
47// Cell writers
48#include "BoundaryNodeWriter.hpp"
49#include "CellProliferativeTypesWriter.hpp"
50#include "LegacyCellProliferativeTypesWriter.hpp"
51#include "CellRemovalLocationsWriter.hpp"
52
53// Cell population writers
54#include "CellMutationStatesCountWriter.hpp"
55#include "CellProliferativePhasesCountWriter.hpp"
56#include "CellProliferativeTypesCountWriter.hpp"
57#include "NodeLocationWriter.hpp"
58
59// These #includes are needed for SetDefaultCellMutationStateAndProliferativeTypeOrdering()
60#include "WildTypeCellMutationState.hpp"
61#include "ApcOneHitCellMutationState.hpp"
62#include "ApcTwoHitCellMutationState.hpp"
63#include "BetaCateninOneHitCellMutationState.hpp"
64#include "DefaultCellProliferativeType.hpp"
65#include "StemCellProliferativeType.hpp"
66#include "TransitCellProliferativeType.hpp"
67#include "DifferentiatedCellProliferativeType.hpp"
68
69template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
71 std::vector<CellPtr>& rCells,
72 const std::vector<unsigned> locationIndices)
73 : mrMesh(rMesh),
74 mCells(rCells.begin(), rCells.end()),
75 mCentroid(zero_vector<double>(SPACE_DIM)),
76 mpCellPropertyRegistry(CellPropertyRegistry::Instance()->TakeOwnership()),
77 mOutputResultsForChasteVisualizer(true)
78{
79 /*
80 * To avoid double-counting problems, clear the passed-in cells vector.
81 * We force a reallocation of memory so that subsequent usage of the
82 * vector is more likely to give an error.
83 */
84 std::vector<CellPtr>().swap(rCells);
85
86 // There must be a one-one correspondence between cells and location indices
87 if (!locationIndices.empty())
88 {
89 if (mCells.size() != locationIndices.size())
90 {
91 EXCEPTION("There is not a one-one correspondence between cells and location indices");
92 }
93 }
94
95 // Set up the map between location indices and cells
96 mLocationCellMap.clear();
97 mCellLocationMap.clear();
98
99 std::list<CellPtr>::iterator it = mCells.begin();
100 for (unsigned i=0; it != mCells.end(); ++it, ++i)
101 {
102 // Give each cell a pointer to the property registry (we have taken ownership in this constructor)
103 (*it)->rGetCellPropertyCollection().SetCellPropertyRegistry(mpCellPropertyRegistry.get());
104 }
105
106 // Clear stored divisions and removals information
109}
110
111template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
117template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
121
122template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
124{
125 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
126 cell_iter!=this->End();
127 ++cell_iter)
128 {
129 cell_iter->InitialiseCellCycleModel();
130 cell_iter->InitialiseSrnModel();
131 }
132}
133
134template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
135void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetDataOnAllCells(const std::string& rDataName, double dataValue)
136{
137 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
138 cell_iter!=this->End();
139 ++cell_iter)
140 {
141 cell_iter->GetCellData()->SetItem(rDataName, dataValue);
142 }
143}
144
145template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
150
151template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
153{
154 return mCells;
155}
156
157template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
159{
160 unsigned counter = 0;
161 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
162 cell_iter!=this->End();
163 ++cell_iter)
164 {
165 counter++;
166 }
167 return counter;
168}
169
170template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
172{
173 return mCells.size();
174}
175
176template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
178{
179 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
180 {
181 MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()]));
182 cell_iter->SetAncestor(p_cell_ancestor);
183 }
184}
185
186template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
188{
189 std::set<unsigned> remaining_ancestors;
190 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
191 {
192 remaining_ancestors.insert(cell_iter->GetAncestor());
193 }
194 return remaining_ancestors;
195}
196
197template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
199{
200 std::vector<unsigned> mutation_state_count;
201 const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
202 = mpCellPropertyRegistry->rGetAllCellProperties();
203
204 // Calculate mutation states count
205 for (unsigned i=0; i<r_cell_properties.size(); i++)
206 {
207 if (r_cell_properties[i]->IsSubType<AbstractCellMutationState>())
209 mutation_state_count.push_back(r_cell_properties[i]->GetCellCount());
210 }
211 }
212
213 // Reduce results onto all processes
215 {
216 // Make sure the vector on each process has the same size
217 unsigned local_size = mutation_state_count.size();
218 unsigned global_size;
219 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
220 assert(local_size == global_size);
221
222 std::vector<unsigned> mutation_counts(global_size);
223 MPI_Allreduce(&mutation_state_count[0], &mutation_counts[0], mutation_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
224
225 mutation_state_count = mutation_counts;
226 }
227
228 return mutation_state_count;
229}
231template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
233{
234 std::vector<unsigned> proliferative_type_count;
235 const std::vector<boost::shared_ptr<AbstractCellProperty> >& r_cell_properties
236 = mpCellPropertyRegistry->rGetAllCellProperties();
237
238 // Calculate proliferative types count
239 for (unsigned i=0; i<r_cell_properties.size(); i++)
240 {
241 if (r_cell_properties[i]->IsSubType<AbstractCellProliferativeType>())
243 proliferative_type_count.push_back(r_cell_properties[i]->GetCellCount());
244 }
245 }
246
247 // Reduce results onto all processes
249 {
250 // Make sure the vector on each process has the same size
251 unsigned local_size = proliferative_type_count.size();
252 unsigned global_size;
253
254 MPI_Allreduce(&local_size, &global_size, 1, MPI_UNSIGNED, MPI_MAX, PetscTools::GetWorld());
255 assert(local_size == global_size);
256
257 std::vector<unsigned> total_types_counts(global_size);
258 MPI_Allreduce(&proliferative_type_count[0], &total_types_counts[0], total_types_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
259
260 proliferative_type_count = total_types_counts;
261 }
262
263 return proliferative_type_count;
264}
265
266template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
269 std::vector<unsigned> cell_cycle_phase_count(5);
270 for (unsigned i=0; i<5; i++)
271 {
272 cell_cycle_phase_count[i] = 0;
273 }
274
275 /*
276 * Note that in parallel with a poor partition a process could end up with zero cells
277 * in which case the calculation should be skipped since `this->Begin()` is not defined.
278 */
279 if (GetNumAllCells() > 0u)
280 {
281 if (dynamic_cast<AbstractPhaseBasedCellCycleModel*>((*(this->Begin()))->GetCellCycleModel()) == nullptr)
282 {
283 EXCEPTION("You are trying to record the cell cycle phase of cells with a non phase based cell cycle model.");
284 }
285
286 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
287 cell_iter != this->End();
288 ++cell_iter)
289 {
290 switch (static_cast<AbstractPhaseBasedCellCycleModel*>((*cell_iter)->GetCellCycleModel())->GetCurrentCellCyclePhase())
291 {
292 case G_ZERO_PHASE:
293 cell_cycle_phase_count[0]++;
294 break;
295 case G_ONE_PHASE:
296 cell_cycle_phase_count[1]++;
297 break;
298 case S_PHASE:
299 cell_cycle_phase_count[2]++;
300 break;
301 case G_TWO_PHASE:
302 cell_cycle_phase_count[3]++;
303 break;
304 case M_PHASE:
305 cell_cycle_phase_count[4]++;
306 break;
307 default:
309 }
310 }
311 }
312
313 // Reduce results onto all processes
315 {
316 std::vector<unsigned> phase_counts(cell_cycle_phase_count.size(), 0u);
317 MPI_Allreduce(&cell_cycle_phase_count[0], &phase_counts[0], phase_counts.size(), MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld());
318
319 cell_cycle_phase_count = phase_counts;
320 }
321
322 return cell_cycle_phase_count;
323}
324
325template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
327{
328 // Get the set of pointers to cells corresponding to this location index
329 std::set<CellPtr> cells = mLocationCellMap[index];
330
331 // If there is only one cell attached return the cell. Note currently only one cell per index.
332 if (cells.size() == 1)
333 {
334 return *(cells.begin());
335 }
336 if (cells.empty())
337 {
338 EXCEPTION("Location index input argument does not correspond to a Cell");
339 }
340 else
341 {
342 EXCEPTION("Multiple cells are attached to a single location index.");
343 }
344}
345
346template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
348{
349 // Return the set of pointers to cells corresponding to this location index, note the set may be empty.
350 return mLocationCellMap[index];
351}
352
353template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
356 // Get the set of pointers to cells corresponding to this location index
357 std::set<CellPtr> cells = mLocationCellMap[index];
358
359 // Return whether there is a cell attached to the location index
360 return !(cells.empty());
361}
362
363template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
367
368template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
370{
371 // Clear the maps
372 mLocationCellMap[index].clear();
373 mCellLocationMap.erase(pCell.get());
374
375 // Replace with new cell
376 mLocationCellMap[index].insert(pCell);
377
378 // Do other half of the map
379 mCellLocationMap[pCell.get()] = index;
380}
381
382template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
384{
385 mLocationCellMap[index].insert(pCell);
386 mCellLocationMap[pCell.get()] = index;
387}
388
389template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
391{
392 std::set<CellPtr>::iterator cell_iter = mLocationCellMap[index].find(pCell);
393
394 if (cell_iter == mLocationCellMap[index].end())
395 {
396 EXCEPTION("Tried to remove a cell which is not attached to the given location index");
397 }
398 else
399 {
400 mLocationCellMap[index].erase(cell_iter);
401 mCellLocationMap.erase(pCell.get());
402 }
403}
404
405template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
406void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::MoveCellInLocationMap(CellPtr pCell, unsigned old_index, unsigned new_index)
407{
408 // Remove the cell from its current location
409 RemoveCellUsingLocationIndex(old_index, pCell);
410
411 // Add it to the new location
412 AddCellUsingLocationIndex(new_index, pCell);
413}
415template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
417{
418 // Check the cell is in the map
419 assert(this->mCellLocationMap.find(pCell.get()) != this->mCellLocationMap.end());
420
421 return mCellLocationMap[pCell.get()];
422}
423
424template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
426{
427 return mpCellPropertyRegistry;
428}
429
430template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
432{
433 boost::shared_ptr<CellPropertyRegistry> p_registry = GetCellPropertyRegistry();
434 if (!p_registry->HasOrderingBeenSpecified())
435 {
436 std::vector<boost::shared_ptr<AbstractCellProperty> > mutations_and_proliferative_types;
437 mutations_and_proliferative_types.push_back(p_registry->Get<WildTypeCellMutationState>());
438 mutations_and_proliferative_types.push_back(p_registry->Get<ApcOneHitCellMutationState>());
439 mutations_and_proliferative_types.push_back(p_registry->Get<ApcTwoHitCellMutationState>());
440 mutations_and_proliferative_types.push_back(p_registry->Get<BetaCateninOneHitCellMutationState>());
441 mutations_and_proliferative_types.push_back(p_registry->Get<StemCellProliferativeType>());
442 mutations_and_proliferative_types.push_back(p_registry->Get<TransitCellProliferativeType>());
443 mutations_and_proliferative_types.push_back(p_registry->Get<DifferentiatedCellProliferativeType>());
444
445 // Parallel process with no cells won't have the default property, so add it in
446 mutations_and_proliferative_types.push_back(p_registry->Get<DefaultCellProliferativeType>());
447 p_registry->SpecifyOrdering(mutations_and_proliferative_types);
448 }
449}
450
451/*
452 * We exclude the following from coverage, as these methods are implemented elsewhere and tested accordingly
453 */
454// LCOV_EXCL_START
455template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
456std::set<std::pair<unsigned, unsigned>> AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringEdgeIndices(CellPtr cell, unsigned pEdgeLocalIndex)
457{
458 return std::set<std::pair<unsigned, unsigned>>();
460// LCOV_EXCL_STOP
461
462template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
464{
465 mCentroid = zero_vector<double>(SPACE_DIM);
466 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
467 cell_iter != this->End();
468 ++cell_iter)
469 {
470 mCentroid += GetLocationOfCellCentre(*cell_iter);
471 }
472 mCentroid /= this->GetNumRealCells();
473
474 return mCentroid;
475}
476
477template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
480}
481
482template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
484{
485 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
486 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
487 {
488 p_cell_writer->CloseFile();
489 }
492 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
493 {
494 p_pop_writer->CloseFile();
495 }
496}
497
498template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
500{
501 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
502 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
503 {
504 p_cell_writer->CloseFile();
505 }
506
508 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
509 {
510 p_pop_writer->CloseFile();
512
513#ifdef CHASTE_VTK
514 *mpVtkMetaFile << " </Collection>\n";
515 *mpVtkMetaFile << "</VTKFile>\n";
516 mpVtkMetaFile->close();
517#endif //CHASTE_VTK
518}
520template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
522{
523#ifdef CHASTE_VTK
524 mpVtkMetaFile = rOutputFileHandler.OpenOutputFile("results.pvd");
525 *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
526 *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
527 *mpVtkMetaFile << " <Collection>\n";
528#endif //CHASTE_VTK
529
530 if (mOutputResultsForChasteVisualizer)
531 {
532 if (!HasWriter<NodeLocationWriter>())
533 {
534 AddPopulationWriter<NodeLocationWriter>();
535 }
536 if (!HasWriter<BoundaryNodeWriter>())
537 {
538 AddPopulationWriter<BoundaryNodeWriter>();
539 }
540 if (!HasWriter<CellProliferativeTypesWriter>())
541 {
542 AddCellWriter<CellProliferativeTypesWriter>();
543 }
544 if (!HasWriter<LegacyCellProliferativeTypesWriter>())
545 {
546 AddCellWriter<LegacyCellProliferativeTypesWriter>();
548 }
549
550 // Open output files for any cell writers
551 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
552 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
553 {
554 p_cell_writer->OpenOutputFile(rOutputFileHandler);
555 }
556
557 // Open output files and write headers for any population writers
559 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
560 {
561 p_pop_writer->OpenOutputFile(rOutputFileHandler);
562 p_pop_writer->WriteHeader(this);
563 }
564
565 // Open output files and write headers for any population count writers
567 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
568 {
569 p_count_writer->OpenOutputFile(rOutputFileHandler);
570 p_count_writer->WriteHeader(this);
571 }
572
573 // Open output files and write headers for any population event writers
575 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
576 {
577 p_event_writer->OpenOutputFile(rOutputFileHandler);
578 p_event_writer->WriteHeader(this);
579 }
580}
581
582template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
584{
585 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
587 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
588 {
589 p_cell_writer->OpenOutputFileForAppend(rOutputFileHandler);
590 }
591 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
592 {
593 p_pop_writer->OpenOutputFileForAppend(rOutputFileHandler);
594 }
595}
596
597template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
599{
600 typedef AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> cell_writer_t;
602 OutputFileHandler output_file_handler(rDirectory, false);
603
604 if (!(mCellWriters.empty() && mCellPopulationWriters.empty() && mCellPopulationCountWriters.empty()))
605 {
606 // An ordering must be specified for cell mutation states and cell proliferative types
607 SetDefaultCellMutationStateAndProliferativeTypeOrdering();
610 {
611 OpenRoundRobinWritersFilesForAppend(output_file_handler);
612
613 // The master process writes time stamps
615 {
616 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
617 {
618 p_cell_writer->WriteTimeStamp();
619 }
620 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
621 {
622 p_pop_writer->WriteTimeStamp();
623 }
624 }
625
626 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator pop_writer_iter = mCellPopulationWriters.begin();
627 pop_writer_iter != mCellPopulationWriters.end();
628 ++pop_writer_iter)
629 {
630 AcceptPopulationWriter(*pop_writer_iter);
631 }
632
633 AcceptCellWritersAcrossPopulation();
634
635 // The top-most process adds a newline
637 {
638 BOOST_FOREACH(boost::shared_ptr<cell_writer_t> p_cell_writer, mCellWriters)
639 {
640 p_cell_writer->WriteNewline();
642 BOOST_FOREACH(boost::shared_ptr<pop_writer_t> p_pop_writer, mCellPopulationWriters)
643 {
644 p_pop_writer->WriteNewline();
645 }
646 }
647 CloseRoundRobinWritersFiles();
650
651 // Outside the round robin, deal with population count writers
653
655 {
656 // Open mCellPopulationCountWriters in append mode for writing, and write time stamps
657 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
658 {
659 p_count_writer->OpenOutputFileForAppend(output_file_handler);
660 p_count_writer->WriteTimeStamp();
661 }
662 }
663 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator count_writer_iter = mCellPopulationCountWriters.begin();
664 count_writer_iter != mCellPopulationCountWriters.end();
665 ++count_writer_iter)
666 {
667 AcceptPopulationCountWriter(*count_writer_iter);
668 }
669
671 {
672 // Add a newline and close any output files
673 BOOST_FOREACH(boost::shared_ptr<count_writer_t> p_count_writer, mCellPopulationCountWriters)
674 {
675 p_count_writer->WriteNewline();
676 p_count_writer->CloseFile();
677 }
678 }
679
680
681 // Outside the round robin, deal with population event writers
683
685 {
686 // Open mCellPopulationCountWriters in append mode for writing
687 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
688 {
689 p_event_writer->OpenOutputFileForAppend(output_file_handler);
690 }
691 }
692 for (typename std::vector<boost::shared_ptr<AbstractCellPopulationEventWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator event_writer_iter = mCellPopulationEventWriters.begin();
693 event_writer_iter != mCellPopulationEventWriters.end();
694 ++event_writer_iter)
695 {
696 AcceptPopulationEventWriter(*event_writer_iter);
697 }
698
700 {
701 // Close any output files
702 BOOST_FOREACH(boost::shared_ptr<event_writer_t> p_event_writer, mCellPopulationEventWriters)
703 {
704 p_event_writer->CloseFile();
706 }
707 }
708
709 // VTK can only be written in 2 or 3 dimensions
710 if (SPACE_DIM > 1)
711 {
712 WriteVtkResultsToFile(rDirectory);
713 }
714}
715
716template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
718{
719 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
720 cell_iter != this->End();
721 ++cell_iter)
722 {
723 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = mCellWriters.begin();
724 cell_writer_iter != mCellWriters.end();
725 ++cell_writer_iter)
726 {
727 AcceptCellWriter(*cell_writer_iter, *cell_iter);
728 }
730}
731
732template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
734{
735 std::string cell_population_type = GetIdentifier();
736
737 *rParamsFile << "\t<" << cell_population_type << ">\n";
738 OutputCellPopulationParameters(rParamsFile);
739 *rParamsFile << "\t</" << cell_population_type << ">\n";
740 *rParamsFile << "\n";
741 *rParamsFile << "\t<CellCycleModels>\n";
742
749 std::set<std::string> unique_cell_cycle_models;
750 std::vector<CellPtr> first_cell_with_unique_CCM;
751 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
752 cell_iter != this->End();
753 ++cell_iter)
754 {
755 std::string identifier = cell_iter->GetCellCycleModel()->GetIdentifier();
756 if (unique_cell_cycle_models.count(identifier) == 0)
757 {
758 unique_cell_cycle_models.insert(identifier);
759 first_cell_with_unique_CCM.push_back((*cell_iter));
761 }
762
763 // Loop over unique cell-cycle models
764 for (unsigned i=0; i<first_cell_with_unique_CCM.size(); i++)
765 {
766 // Output cell-cycle model details
767 first_cell_with_unique_CCM[i]->GetCellCycleModel()->OutputCellCycleModelInfo(rParamsFile);
768 }
769 *rParamsFile << "\t</CellCycleModels>\n";
771 *rParamsFile << "\n";
772 *rParamsFile << "\t<SrnModels>\n";
773
780 std::set<std::string> unique_srn_models;
781 std::vector<CellPtr> first_cell_with_unique_SRN;
782 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
783 cell_iter != this->End();
784 ++cell_iter)
785 {
786 std::string identifier = cell_iter->GetSrnModel()->GetIdentifier();
787 if (unique_srn_models.count(identifier) == 0)
788 {
789 unique_srn_models.insert(identifier);
790 first_cell_with_unique_SRN.push_back((*cell_iter));
792 }
793
794 // Loop over unique SRN models
795 for (unsigned i=0; i<first_cell_with_unique_SRN.size(); i++)
796 {
797 // Output SRN model details
798 first_cell_with_unique_SRN[i]->GetSrnModel()->OutputSrnModelInfo(rParamsFile);
799 }
800
801 *rParamsFile << "\t</SrnModels>\n";
802}
803
804template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
806{
807 *rParamsFile << "\t\t<OutputResultsForChasteVisualizer>" << mOutputResultsForChasteVisualizer << "</OutputResultsForChasteVisualizer>\n";
808}
809
810template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
814
815template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
817{
818 return mOutputResultsForChasteVisualizer;
819}
820
821template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
823{
824 mOutputResultsForChasteVisualizer = outputResultsForChasteVisualizer;
825}
826
827template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
829{
830 return mDivisionsInformation;
831}
832template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
834{
835 mDivisionsInformation.push_back(divisionInformation);
836}
837
838template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
840{
841 mDivisionsInformation.clear();
842}
843
844template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
846{
847 return mRemovalsInformation;
848}
849
850template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
852{
853 mRemovalsInformation.push_back(removalInformation);
854}
855
856template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
858{
859 mRemovalsInformation.clear();
860}
861
862template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
864{
865 //If necessary store the information about the cell removal
866 c_vector<double, SPACE_DIM> cell_location = GetLocationOfCellCentre(pCell);
867 if (HasWriter<CellRemovalLocationsWriter>())
868 {
869 std::stringstream removal_info;
870 removal_info << SimulationTime::Instance()->GetTime() << "\t";
871 for (unsigned i = 0; i < SPACE_DIM; i++)
872 {
873 removal_info << cell_location[i] << "\t";
874 }
875 removal_info << "\t" << pCell->GetAge() << "\t" << pCell->GetCellId() << "\t" << killerInfo << "\t";
876
877 AddRemovalInformation(removal_info.str());
878 }
879}
880
881template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
882void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::KillCell(CellPtr pCell, std::string killerInfo)
883{
884 //If necessary store the information about the cell removal
885 GenerateRemovalInformation(pCell, killerInfo);
886
887 //Mark cell as dead
888 pCell->Kill();
889}
890
891template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
893{
894 //If necessary store the information about the cell removal
895 GenerateRemovalInformation(pCell, killerInfo);
896
897 //Mark cell as Apoptotic
898 pCell->StartApoptosis();
899}
900
901template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
903{
904 return true;
905}
906
907template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
909{
910 // Compute the centre of mass of the cell population
911 c_vector<double,SPACE_DIM> centre = GetCentroidOfCellPopulation();
912
913 // Loop over cells and find the maximum distance from the centre of mass in each dimension
914 c_vector<double,SPACE_DIM> max_distance_from_centre = zero_vector<double>(SPACE_DIM);
915 for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
916 cell_iter != this->End();
917 ++cell_iter)
918 {
919 c_vector<double,SPACE_DIM> cell_location = GetLocationOfCellCentre(*cell_iter);
920
921 // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
922 c_vector<double,SPACE_DIM> displacement;
923 displacement = centre - cell_location;
924
925 for (unsigned i=0; i<SPACE_DIM; i++)
926 {
927 if (displacement[i] > max_distance_from_centre[i])
928 {
929 max_distance_from_centre[i] = displacement[i];
930 }
931 }
932 }
933
934 return max_distance_from_centre;
935}
936
937template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
938std::pair<unsigned,unsigned> AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOrderedPair(unsigned index1, unsigned index2)
939{
940 assert(index1 != index2);
941
942 std::pair<unsigned, unsigned> ordered_pair;
943 if (index1 < index2)
944 {
945 ordered_pair.first = index1;
946 ordered_pair.second = index2;
947 }
948 else
949 {
950 ordered_pair.first = index2;
951 ordered_pair.second = index1;
952 }
953 return ordered_pair;
954}
955
956template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
958{
959 bool non_apoptotic_cell_present = false;
961 if (IsCellAttachedToLocationIndex(pdeNodeIndex))
962 {
963 non_apoptotic_cell_present = !(GetCellUsingLocationIndex(pdeNodeIndex)->template HasCellProperty<ApoptoticCellProperty>());
964 }
965
966 return non_apoptotic_cell_present;
967}
968
969
970// Explicit instantiation
971template class AbstractCellPopulation<1,1>;
972template class AbstractCellPopulation<1,2>;
973template class AbstractCellPopulation<2,2>;
974template class AbstractCellPopulation<1,3>;
975template class AbstractCellPopulation<2,3>;
976template 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()