Chaste Commit::1fd4e48e3990e67db148bc1bc4cf6991a0049d0c
Cell.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 "Cell.hpp"
37
38#include "ApoptoticCellProperty.hpp"
39#include "CellAncestor.hpp"
40#include "CellId.hpp"
41#include "CellLabel.hpp"
42#include "DefaultCellProliferativeType.hpp"
43#include "NullSrnModel.hpp"
44#include "SmartPointers.hpp"
45
46Cell::Cell(boost::shared_ptr<AbstractCellProperty> pMutationState,
47 AbstractCellCycleModel* pCellCycleModel,
48 AbstractSrnModel* pSrnModel,
49 bool archiving,
50 CellPropertyCollection cellPropertyCollection)
51 : mCanDivide(false),
52 mCellPropertyCollection(cellPropertyCollection),
53 mpCellCycleModel(pCellCycleModel),
54 mpSrnModel(pSrnModel),
55 mDeathTime(DBL_MAX), // This has to be initialised for archiving
56 mStartOfApoptosisTime(DBL_MAX),
57 mApoptosisTime(0.25), // cell takes 15 min to fully undergo apoptosis
58 mUndergoingApoptosis(false),
59 mIsDead(false),
60 mIsLogged(false),
61 mHasSrnModel(false)
62{
63 if (SimulationTime::Instance()->IsStartTimeSetUp()==false)
64 {
65 EXCEPTION("Cell is setting up a cell-cycle model but SimulationTime has not been set up");
66 }
67
68 if (pCellCycleModel == nullptr)
69 {
70 EXCEPTION("Cell-cycle model is null");
71 }
72
73 mpCellCycleModel->SetCell(CellPtr(this, null_deleter()));
74
75 // Create a null SRN model if none given
76 if (pSrnModel == nullptr)
77 {
78 pSrnModel = new NullSrnModel;
79 mpSrnModel = pSrnModel;
80 }
81 else
82 {
83 mHasSrnModel = true;
84 }
85
86 mpSrnModel->SetCell(CellPtr(this, null_deleter()));
87
89 {
90 // Set cell identifier this will be called all the time unless the constructor is called through archiving
91 MAKE_PTR(CellId, p_cell_id);
92 p_cell_id->AssignCellId();
94 }
95
96 if (!pMutationState->IsSubType<AbstractCellMutationState>())
97 {
98 EXCEPTION("Attempting to create cell with a cell mutation state that is not a subtype of AbstractCellMutationState");
99 }
100
101 if (!mCellPropertyCollection.HasProperty(pMutationState))
102 {
103 mCellPropertyCollection.AddProperty(pMutationState);
104 }
105
107 {
108 // Add empty cell data
109 MAKE_PTR(CellData, p_cell_data);
111 }
112
114 {
115 // Add empty cell edge data
116 MAKE_PTR(CellEdgeData, p_cell_edge_data);
117 mCellPropertyCollection.AddProperty(p_cell_edge_data);
118 }
119
120 /*
121 * If a cell proliferative type was not passed in via the input
122 * argument cellPropertyCollection (for example as in the case
123 * of a daughter cell being created following division) then add
124 * add a 'default' cell proliferative type to the cell property
125 * collection. This ensures that the method GetCellProliferativeType()
126 * always returns a valid proliferative type.
127 */
129 {
130 mCellPropertyCollection.AddProperty(CellPropertyRegistry::Instance()->Get<DefaultCellProliferativeType>());
131 }
132
133 if (!archiving)
134 {
135 // Increment cell count for each cell property in mCellPropertyCollection
137 property_iter != mCellPropertyCollection.End();
138 ++property_iter)
139 {
140 (*property_iter)->IncrementCellCount();
141 }
142 }
143}
144
146{
147 if (!mIsDead)
148 {
149 Kill();
150 }
151 delete mpCellCycleModel;
152 delete mpSrnModel;
153}
154
155void Cell::SetCellProliferativeType(boost::shared_ptr<AbstractCellProperty> pProliferativeType)
156{
157 if (!pProliferativeType->IsSubType<AbstractCellProliferativeType>())
158 {
159 EXCEPTION("Attempting to give cell a cell proliferative type that is not a subtype of AbstractCellProliferativeType");
160 }
161
162 boost::shared_ptr<AbstractCellProliferativeType> p_old_proliferative_type = GetCellProliferativeType();
163
164 p_old_proliferative_type->DecrementCellCount();
165 mCellPropertyCollection.RemoveProperty(p_old_proliferative_type);
166
167 AddCellProperty(pProliferativeType);
168}
169
170boost::shared_ptr<AbstractCellProliferativeType> Cell::GetCellProliferativeType() const
171{
173
174 /*
175 * Note: In its current form the code requires each cell to have exactly
176 * one proliferative type. This is reflected in the assertion below. If a user
177 * wishes to include cells with multiple proliferative types, each possible
178 * combination must be created as a separate proliferative type class.
179 */
180 assert(proliferative_type_collection.GetSize() == 1);
181
182 return boost::static_pointer_cast<AbstractCellProliferativeType>(proliferative_type_collection.GetProperty());
183}
184
186{
187 if (mpCellCycleModel != pCellCycleModel)
188 {
189 delete mpCellCycleModel;
190 }
191 mpCellCycleModel = pCellCycleModel;
192 mpCellCycleModel->SetCell(CellPtr(this, null_deleter()));
193}
194
199
204
206{
207 if (mpSrnModel != pSrnModel)
208 {
209 delete mpSrnModel;
210 }
211 mpSrnModel = pSrnModel;
212 mpSrnModel->SetCell(CellPtr(this, null_deleter()));
213 mHasSrnModel = true;
214}
215
217{
218 return mpSrnModel;
219}
220
225
226double Cell::GetAge() const
227{
228 return mpCellCycleModel->GetAge();
229}
230
231double Cell::GetBirthTime() const
232{
234}
235
236void Cell::SetBirthTime(double birthTime)
237{
238 mpCellCycleModel->SetBirthTime(birthTime);
239}
240
241void Cell::SetMutationState(boost::shared_ptr<AbstractCellProperty> pMutationState)
242{
243 if (!pMutationState->IsSubType<AbstractCellMutationState>())
244 {
245 EXCEPTION("Attempting to give cell a cell mutation state that is not a subtype of AbstractCellMutationState");
246 }
247
248 boost::shared_ptr<AbstractCellMutationState> p_old_mutation_state = GetMutationState();
249 p_old_mutation_state->DecrementCellCount();
250 mCellPropertyCollection.RemoveProperty(p_old_mutation_state);
251
252 AddCellProperty(pMutationState);
253}
254
255boost::shared_ptr<AbstractCellMutationState> Cell::GetMutationState() const
256{
258
259 /*
260 * Note: In its current form the code requires each cell to have exactly
261 * one mutation state. This is reflected in the assertion below. If a user
262 * wishes to include cells with multiple mutation states, each possible
263 * combination must be created as a separate mutation state class.
264 */
265 assert(mutation_state_collection.GetSize() == 1);
266
267 return boost::static_pointer_cast<AbstractCellMutationState>(mutation_state_collection.GetProperty());
268}
269
270boost::shared_ptr<CellData> Cell::GetCellData() const
271{
273
274 /*
275 * Note: In its current form the code requires each cell to have exactly
276 * one CellData object. This is reflected in the assertion below.
277 */
278 assert(cell_data_collection.GetSize() <= 1);
279
280 return boost::static_pointer_cast<CellData>(cell_data_collection.GetProperty());
281}
282
283boost::shared_ptr<CellEdgeData> Cell::GetCellEdgeData() const
284{
286
287 /*
288 * Note: In its current form the code requires each cell to have exactly
289 * one CellEdgeData object. This is reflected in the assertion below.
290 */
291 assert(collection.GetSize() <= 1);
292
293 return boost::static_pointer_cast<CellEdgeData>(collection.GetProperty());
294}
295
300
301boost::shared_ptr<CellVecData> Cell::GetCellVecData() const
302{
303 assert(HasCellVecData());
304
306
307 /*
308 * Note: In its current form the code requires each cell to have exactly
309 * one CellVecData object. This is reflected in the assertion below.
310 */
311 assert(cell_data_collection.GetSize() <= 1);
312
313 return boost::static_pointer_cast<CellVecData>(cell_data_collection.GetProperty());
314}
315
320
325
326void Cell::AddCellProperty(const boost::shared_ptr<AbstractCellProperty>& rProperty)
327{
328 // Note: if the cell already has the specified property, no action is taken
329 if (!mCellPropertyCollection.HasProperty(rProperty))
330 {
332 rProperty->IncrementCellCount();
333 }
334}
335
337{
338 mIsLogged = true;
339}
340
342{
343 return mIsLogged;
344}
345
346void Cell::StartApoptosis(bool setDeathTime)
347{
348 assert(!IsDead());
349
351 {
352 EXCEPTION("StartApoptosis() called when already undergoing apoptosis");
353 }
356 if (setDeathTime)
357 {
359 }
360 else
361 {
362 mDeathTime = DBL_MAX;
363 }
365}
366
368{
370}
371
373{
375}
376
378{
379 return mApoptosisTime;
380}
381
382void Cell::SetApoptosisTime(double apoptosisTime)
383{
384 assert(apoptosisTime > 0.0);
385 mApoptosisTime = apoptosisTime;
386}
387
389{
390 if (!mUndergoingApoptosis || mDeathTime==DBL_MAX)
391 {
392 EXCEPTION("Shouldn't be checking time until apoptosis as it isn't set");
393 }
394
396}
397
399{
401 {
402 double sloppy_death_time = mDeathTime - DBL_EPSILON * mApoptosisTime;
403 if (SimulationTime::Instance()->GetTime() >= sloppy_death_time )
404 {
405 this->Kill();
406 }
407 }
408 return mIsDead;
409}
410
412{
413 // Decrement cell count for each cell property in mCellPropertyCollection
415 property_iter != mCellPropertyCollection.End();
416 ++property_iter)
417 {
418 (*property_iter)->DecrementCellCount();
419 }
420 mIsDead = true;
421}
422
423void Cell::SetAncestor(boost::shared_ptr<AbstractCellProperty> pCellAncestor)
424{
425 if (!pCellAncestor->IsSubType<CellAncestor>())
426 {
427 EXCEPTION("Attempting to give cell a cell ancestor which is not a CellAncestor");
428 }
429
430 // You can only set ancestors once
432 if (ancestor_collection.GetSize() == 0)
433 {
434 AddCellProperty(pCellAncestor);
435 }
436 else
437 {
438 // Overwrite the CellAncestor
439 RemoveCellProperty<CellAncestor>();
440 AddCellProperty(pCellAncestor);
441 }
442}
443
444unsigned Cell::GetAncestor() const
445{
447
448 assert(ancestor_collection.GetSize() <= 1);
449 if (ancestor_collection.GetSize() == 0)
450 {
451 return UNSIGNED_UNSET;
452 }
453
454 boost::shared_ptr<CellAncestor> p_ancestor = boost::static_pointer_cast<CellAncestor>(ancestor_collection.GetProperty());
455
456 return p_ancestor->GetAncestor();
457}
458
459unsigned Cell::GetCellId() const
460{
462
463 assert(cell_id_collection.GetSize() == 1);
464
465 boost::shared_ptr<CellId> p_cell_id = boost::static_pointer_cast<CellId>(cell_id_collection.GetProperty());
466
467 return p_cell_id->GetCellId();
468}
469
471{
472 assert(!IsDead());
473 if (mUndergoingApoptosis || HasCellProperty<ApoptoticCellProperty>())
474 {
475 return false;
476 }
477
478 // NOTE - we run the SRN model here first before the CCM
480
481 // This in turn runs any simulations within the CCM through ReadyToDivide();
483
484 return mCanDivide;
485}
486
488{
489 // Check we're allowed to divide
490 assert(!IsDead());
491 assert(mCanDivide);
492 mCanDivide = false;
493
494 // Reset properties of parent cell
497
498 // Create copy of cell property collection to modify for daughter cell
499 CellPropertyCollection daughter_property_collection = mCellPropertyCollection;
500
501 // Remove the CellId from the daughter cell, as a new one will be assigned in the constructor
502 daughter_property_collection.RemoveProperty<CellId>();
503
504 // Copy all cell data (note we create a new object not just copying the pointer)
505 assert(daughter_property_collection.HasPropertyType<CellData>());
506
507 // Get the existing copy of the cell data and remove it from the daughter cell
508 boost::shared_ptr<CellData> p_cell_data = GetCellData();
509 daughter_property_collection.RemoveProperty(p_cell_data);
510
511 // Create a new cell data object using the copy constructor and add this to the daughter cell
512 MAKE_PTR_ARGS(CellData, p_daughter_cell_data, (*p_cell_data));
513 daughter_property_collection.AddProperty(p_daughter_cell_data);
514
515 // Get the existing copy of the cell edge data and remove it from the daughter cell
516 boost::shared_ptr<CellEdgeData> p_cell_edge_data = GetCellEdgeData();
517 daughter_property_collection.RemoveProperty(p_cell_edge_data);
518
519 // Create a new cell edge data object using the copy constructor and add this to the daughter cell
520 MAKE_PTR_ARGS(CellEdgeData, p_daughter_cell_edge_data, (*p_cell_edge_data));
521 daughter_property_collection.AddProperty(p_daughter_cell_edge_data);
522
523 // Copy all cell Vec data (note we create a new object not just copying the pointer)
524 if (daughter_property_collection.HasPropertyType<CellVecData>())
525 {
526 // Get the existing copy of the cell data and remove it from the daughter cell
527 boost::shared_ptr<CellVecData> p_cell_vec_data = GetCellVecData();
528 daughter_property_collection.RemoveProperty(p_cell_vec_data);
529
530 // Create a new cell data object using the copy constructor and add this to the daughter cell
531 MAKE_PTR_ARGS(CellVecData, p_daughter_cell_vec_data, (*p_cell_vec_data));
532 daughter_property_collection.AddProperty(p_daughter_cell_vec_data);
533 }
534
535 // Create daughter cell with modified cell property collection
536 CellPtr p_new_cell(new Cell(GetMutationState(), mpCellCycleModel->CreateCellCycleModel(), mpSrnModel->CreateSrnModel(), false, daughter_property_collection));
537
538 // Initialise properties of daughter cell
539 p_new_cell->GetCellCycleModel()->InitialiseDaughterCell();
540 p_new_cell->GetSrnModel()->InitialiseDaughterCell();
541
542 // Set the daughter cell to inherit the apoptosis time of the parent cell
543 p_new_cell->SetApoptosisTime(mApoptosisTime);
544
545 return p_new_cell;
546}
547
549{
550 return mHasSrnModel;
551}
#define EXCEPTION(message)
const unsigned UNSIGNED_UNSET
Definition Exception.hpp:53
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
#define MAKE_PTR(TYPE, NAME)
virtual void SetBirthTime(double birthTime)
virtual AbstractCellCycleModel * CreateCellCycleModel()=0
virtual bool ReadyToDivide()=0
virtual void SimulateToCurrentTime()=0
virtual AbstractSrnModel * CreateSrnModel()=0
virtual void SetCell(CellPtr pCell)
virtual void ResetForDivision()
virtual void Initialise()
bool HasProperty(const boost::shared_ptr< AbstractCellProperty > &rProp) const
boost::shared_ptr< AbstractCellProperty > GetProperty() const
CollectionType::iterator Iterator
CellPropertyCollection GetPropertiesType() const
void AddProperty(const boost::shared_ptr< AbstractCellProperty > &rProp)
CellPropertyRegistry * GetCellPropertyRegistry()
static CellPropertyRegistry * Instance()
boost::shared_ptr< AbstractCellProperty > Get()
Definition Cell.hpp:92
double mDeathTime
Definition Cell.hpp:134
double GetAge() const
Definition Cell.cpp:226
void Kill()
Definition Cell.cpp:411
bool mIsLogged
Definition Cell.hpp:152
void SetLogged()
Definition Cell.cpp:336
bool mHasSrnModel
Definition Cell.hpp:155
bool HasSrnModel() const
Definition Cell.cpp:548
unsigned GetCellId() const
Definition Cell.cpp:459
AbstractSrnModel * GetSrnModel() const
Definition Cell.cpp:216
AbstractCellCycleModel * GetCellCycleModel() const
Definition Cell.cpp:195
void InitialiseSrnModel()
Definition Cell.cpp:221
AbstractSrnModel * mpSrnModel
Definition Cell.hpp:131
AbstractCellCycleModel * mpCellCycleModel
Definition Cell.hpp:128
bool HasCellVecData() const
Definition Cell.cpp:296
void SetSrnModel(AbstractSrnModel *pSrnModel)
Definition Cell.cpp:205
Cell(boost::shared_ptr< AbstractCellProperty > pMutationState, AbstractCellCycleModel *pCellCycleModel, AbstractSrnModel *pSrnModel=nullptr, bool archiving=false, CellPropertyCollection cellPropertyCollection=CellPropertyCollection())
Definition Cell.cpp:46
double mStartOfApoptosisTime
Definition Cell.hpp:137
double GetBirthTime() const
Definition Cell.cpp:231
bool IsDead()
Definition Cell.cpp:398
double GetStartOfApoptosisTime() const
Definition Cell.cpp:372
void AddCellProperty(const boost::shared_ptr< AbstractCellProperty > &rProperty)
Definition Cell.cpp:326
void SetBirthTime(double birthTime)
Definition Cell.cpp:236
boost::shared_ptr< AbstractCellProliferativeType > GetCellProliferativeType() const
Definition Cell.cpp:170
CellPropertyCollection mCellPropertyCollection
Definition Cell.hpp:125
bool mUndergoingApoptosis
Definition Cell.hpp:143
bool mCanDivide
Definition Cell.hpp:122
void SetCellCycleModel(AbstractCellCycleModel *pCellCycleModel)
Definition Cell.cpp:185
boost::shared_ptr< CellData > GetCellData() const
Definition Cell.cpp:270
bool mIsDead
Definition Cell.hpp:149
bool HasApoptosisBegun() const
Definition Cell.cpp:367
unsigned GetAncestor() const
Definition Cell.cpp:444
boost::shared_ptr< CellVecData > GetCellVecData() const
Definition Cell.cpp:301
virtual ~Cell()
Definition Cell.cpp:145
bool ReadyToDivide()
Definition Cell.cpp:470
void SetApoptosisTime(double apoptosisTime)
Definition Cell.cpp:382
double GetApoptosisTime() const
Definition Cell.cpp:377
CellPropertyCollection & rGetCellPropertyCollection()
Definition Cell.cpp:316
boost::shared_ptr< CellEdgeData > GetCellEdgeData() const
Definition Cell.cpp:283
void SetMutationState(boost::shared_ptr< AbstractCellProperty > pMutationState)
Definition Cell.cpp:241
void SetCellProliferativeType(boost::shared_ptr< AbstractCellProperty > pProliferativeType)
Definition Cell.cpp:155
double mApoptosisTime
Definition Cell.hpp:140
void SetAncestor(boost::shared_ptr< AbstractCellProperty > pCellAncestor)
Definition Cell.cpp:423
void StartApoptosis(bool setDeathTime=true)
Definition Cell.cpp:346
double GetTimeUntilDeath() const
Definition Cell.cpp:388
void InitialiseCellCycleModel()
Definition Cell.cpp:200
virtual CellPtr Divide()
Definition Cell.cpp:487
boost::shared_ptr< AbstractCellMutationState > GetMutationState() const
Definition Cell.cpp:255
bool IsLogged()
Definition Cell.cpp:341
double GetTime() const
static SimulationTime * Instance()