Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "Cell.hpp" 00037 #include "ApoptoticCellProperty.hpp" 00038 00051 struct null_deleter 00052 { 00054 void operator()(void const *) const 00055 { 00056 } 00057 }; 00058 00059 Cell::Cell(boost::shared_ptr<AbstractCellProperty> pMutationState, 00060 AbstractCellCycleModel* pCellCycleModel, 00061 bool archiving, 00062 CellPropertyCollection cellPropertyCollection) 00063 : mCanDivide(false), 00064 mCellPropertyCollection(cellPropertyCollection), 00065 mpCellCycleModel(pCellCycleModel), 00066 mDeathTime(DBL_MAX), // This has to be initialised for archiving 00067 mStartOfApoptosisTime(DBL_MAX), 00068 mApoptosisTime(0.25), // cell takes 15 min to fully undergo apoptosis 00069 mUndergoingApoptosis(false), 00070 mIsDead(false), 00071 mIsLogged(false) 00072 { 00073 if (SimulationTime::Instance()->IsStartTimeSetUp()==false) 00074 { 00075 EXCEPTION("Cell is setting up a cell-cycle model but SimulationTime has not been set up"); 00076 } 00077 00078 if (pCellCycleModel == NULL) 00079 { 00080 EXCEPTION("Cell-cycle model is null"); 00081 } 00082 00083 mpCellCycleModel->SetCell(CellPtr(this, null_deleter())); 00084 00085 00086 if (!mCellPropertyCollection.HasPropertyType<CellId>()) 00087 { 00088 // Set cell identifier this will be called all the time unless the constructor is called through archiving 00089 MAKE_PTR(CellId, p_cell_id); 00090 p_cell_id->AssignCellId(); 00091 mCellPropertyCollection.AddProperty(p_cell_id); 00092 } 00093 00094 if (!pMutationState->IsSubType<AbstractCellMutationState>()) 00095 { 00096 EXCEPTION("Attempting to create cell with a cell mutation state is not a subtype of AbstractCellMutationState"); 00097 } 00098 00099 if (!mCellPropertyCollection.HasProperty(pMutationState)) 00100 { 00101 mCellPropertyCollection.AddProperty(pMutationState); 00102 } 00103 00104 if (!mCellPropertyCollection.HasPropertyType<CellData>()) 00105 { 00106 // Add empty cell data 00107 MAKE_PTR(CellData, p_cell_data); 00108 mCellPropertyCollection.AddProperty(p_cell_data); 00109 } 00110 00111 if (!archiving) 00112 { 00113 // Increment cell count for each cell property in mCellPropertyCollection 00114 for (CellPropertyCollection::Iterator property_iter = mCellPropertyCollection.Begin(); 00115 property_iter != mCellPropertyCollection.End(); 00116 ++property_iter) 00117 { 00118 (*property_iter)->IncrementCellCount(); 00119 } 00120 } 00121 } 00122 00123 Cell::~Cell() 00124 { 00125 if (!mIsDead) 00126 { 00127 Kill(); 00128 } 00129 delete mpCellCycleModel; 00130 } 00131 00132 void Cell::SetCellProliferativeType(CellProliferativeType cellType) 00133 { 00134 mCellProliferativeType = cellType; 00135 } 00136 00137 CellProliferativeType Cell::GetCellProliferativeType() const 00138 { 00139 return mCellProliferativeType; 00140 } 00141 00142 void Cell::SetCellCycleModel(AbstractCellCycleModel* pCellCycleModel) 00143 { 00144 if (mpCellCycleModel != pCellCycleModel) 00145 { 00146 delete mpCellCycleModel; 00147 } 00148 mpCellCycleModel = pCellCycleModel; 00149 mpCellCycleModel->SetCell(CellPtr(this, null_deleter())); 00150 } 00151 00152 AbstractCellCycleModel* Cell::GetCellCycleModel() const 00153 { 00154 return mpCellCycleModel; 00155 } 00156 00157 void Cell::InitialiseCellCycleModel() 00158 { 00159 mpCellCycleModel->Initialise(); 00160 } 00161 00162 double Cell::GetAge() const 00163 { 00164 return mpCellCycleModel->GetAge(); 00165 } 00166 00167 double Cell::GetBirthTime() const 00168 { 00169 return mpCellCycleModel->GetBirthTime(); 00170 } 00171 00172 void Cell::SetBirthTime(double birthTime) 00173 { 00174 mpCellCycleModel->SetBirthTime(birthTime); 00175 } 00176 00177 void Cell::SetMutationState(boost::shared_ptr<AbstractCellProperty> pMutationState) 00178 { 00179 if (!pMutationState->IsSubType<AbstractCellMutationState>()) 00180 { 00181 EXCEPTION("Attempting to give cell a cell mutation state is not a subtype of AbstractCellMutationState"); 00182 } 00183 00184 boost::shared_ptr<AbstractCellMutationState> p_old_mutation_state = GetMutationState(); 00185 p_old_mutation_state->DecrementCellCount(); 00186 mCellPropertyCollection.RemoveProperty(p_old_mutation_state); 00187 00188 AddCellProperty(pMutationState); 00189 } 00190 00191 boost::shared_ptr<AbstractCellMutationState> Cell::GetMutationState() const 00192 { 00193 CellPropertyCollection mutation_state_collection = mCellPropertyCollection.GetPropertiesType<AbstractCellMutationState>(); 00194 00195 /* 00196 * Note: In its current form the code requires each cell to have exactly 00197 * one mutation state. This is reflected in the assertion below. If a user 00198 * wishes to include cells with multiple mutation states, each possible 00199 * combination must be created as a separate mutation state class. 00200 */ 00201 assert(mutation_state_collection.GetSize() == 1); 00202 00203 return boost::static_pointer_cast<AbstractCellMutationState>(mutation_state_collection.GetProperty()); 00204 } 00205 00206 boost::shared_ptr<CellData> Cell::GetCellData() const 00207 { 00208 CellPropertyCollection cell_data_collection = mCellPropertyCollection.GetPropertiesType<CellData>(); 00209 00210 /* 00211 * Note: In its current form the code requires each cell to have exactly 00212 * one CellData object. This is reflected in the assertion below. 00213 */ 00214 assert(cell_data_collection.GetSize() <= 1); 00215 00216 return boost::static_pointer_cast<CellData>(cell_data_collection.GetProperty()); 00217 } 00218 00219 CellPropertyCollection& Cell::rGetCellPropertyCollection() 00220 { 00221 return mCellPropertyCollection; 00222 } 00223 00224 const CellPropertyCollection& Cell::rGetCellPropertyCollection() const 00225 { 00226 return mCellPropertyCollection; 00227 } 00228 00229 void Cell::AddCellProperty(const boost::shared_ptr<AbstractCellProperty>& rProperty) 00230 { 00231 // Note: if the cell already has the specified property, no action is taken 00232 if (!mCellPropertyCollection.HasProperty(rProperty)) 00233 { 00234 mCellPropertyCollection.AddProperty(rProperty); 00235 rProperty->IncrementCellCount(); 00236 } 00237 } 00238 00239 void Cell::SetLogged() 00240 { 00241 mIsLogged = true; 00242 } 00243 00244 bool Cell::IsLogged() 00245 { 00246 return mIsLogged; 00247 } 00248 00249 void Cell::StartApoptosis(bool setDeathTime) 00250 { 00251 assert(!IsDead()); 00252 00253 if (mUndergoingApoptosis) 00254 { 00255 EXCEPTION("StartApoptosis() called when already undergoing apoptosis"); 00256 } 00257 mUndergoingApoptosis = true; 00258 mStartOfApoptosisTime = SimulationTime::Instance()->GetTime(); 00259 if (setDeathTime) 00260 { 00261 mDeathTime = mStartOfApoptosisTime + mApoptosisTime; 00262 } 00263 else 00264 { 00265 mDeathTime = DBL_MAX; 00266 } 00267 AddCellProperty(mCellPropertyCollection.GetCellPropertyRegistry()->Get<ApoptoticCellProperty>()); 00268 } 00269 00270 bool Cell::HasApoptosisBegun() const 00271 { 00272 return mUndergoingApoptosis; 00273 } 00274 00275 double Cell::GetStartOfApoptosisTime() const 00276 { 00277 return mStartOfApoptosisTime; 00278 } 00279 00280 double Cell::GetApoptosisTime() const 00281 { 00282 return mApoptosisTime; 00283 } 00284 00285 void Cell::SetApoptosisTime(double apoptosisTime) 00286 { 00287 assert(apoptosisTime > 0.0); 00288 mApoptosisTime = apoptosisTime; 00289 } 00290 00291 double Cell::GetTimeUntilDeath() const 00292 { 00293 if (!mUndergoingApoptosis || mDeathTime==DBL_MAX) 00294 { 00295 EXCEPTION("Shouldn't be checking time until apoptosis as it isn't set"); 00296 } 00297 00298 return mDeathTime - SimulationTime::Instance()->GetTime(); 00299 } 00300 00301 bool Cell::IsDead() 00302 { 00303 if (mUndergoingApoptosis && !mIsDead) 00304 { 00305 double sloppy_death_time = mDeathTime - DBL_EPSILON * mApoptosisTime; 00306 if (SimulationTime::Instance()->GetTime() >= sloppy_death_time ) 00307 { 00308 this->Kill(); 00309 } 00310 } 00311 return mIsDead; 00312 } 00313 00314 void Cell::Kill() 00315 { 00316 // Decrement cell count for each cell property in mCellPropertyCollection 00317 for (CellPropertyCollection::Iterator property_iter = mCellPropertyCollection.Begin(); 00318 property_iter != mCellPropertyCollection.End(); 00319 ++property_iter) 00320 { 00321 (*property_iter)->DecrementCellCount(); 00322 } 00323 mIsDead = true; 00324 } 00325 00326 void Cell::SetAncestor(boost::shared_ptr<AbstractCellProperty> pCellAncestor) 00327 { 00328 if (!pCellAncestor->IsSubType<CellAncestor>()) 00329 { 00330 EXCEPTION("Attempting to give cell a cell ancestor which is not a CellAncestor"); 00331 } 00332 00333 // You can only set ancestors once 00334 CellPropertyCollection ancestor_collection = mCellPropertyCollection.GetPropertiesType<CellAncestor>(); 00335 if (ancestor_collection.GetSize() == 0) 00336 { 00337 AddCellProperty(pCellAncestor); 00338 } 00339 else 00340 { 00341 // Over-write the CellAncestor 00342 RemoveCellProperty<CellAncestor>(); 00343 AddCellProperty(pCellAncestor); 00344 } 00345 00346 } 00347 00348 unsigned Cell::GetAncestor() const 00349 { 00350 CellPropertyCollection ancestor_collection = mCellPropertyCollection.GetPropertiesType<CellAncestor>(); 00351 00352 assert(ancestor_collection.GetSize() <= 1); 00353 if (ancestor_collection.GetSize() == 0) 00354 { 00355 return UNSIGNED_UNSET; 00356 //EXCEPTION("SetAncestor must be called before GetAncestor. You may want to call SetCellAncestorsToLocationIndices on the cell population."); 00357 } 00358 00359 boost::shared_ptr<CellAncestor> p_ancestor = boost::static_pointer_cast<CellAncestor>(ancestor_collection.GetProperty()); 00360 00361 return p_ancestor->GetAncestor(); 00362 } 00363 00364 unsigned Cell::GetCellId() const 00365 { 00366 CellPropertyCollection cell_id_collection = mCellPropertyCollection.GetPropertiesType<CellId>(); 00367 00368 assert(cell_id_collection.GetSize() == 1); 00369 00370 boost::shared_ptr<CellId> p_cell_id = boost::static_pointer_cast<CellId>(cell_id_collection.GetProperty()); 00371 00372 return p_cell_id->GetCellId(); 00373 } 00374 00375 bool Cell::ReadyToDivide() 00376 { 00377 assert(!IsDead()); 00378 if (mUndergoingApoptosis || HasCellProperty<ApoptoticCellProperty>()) 00379 { 00380 return false; 00381 } 00382 00383 mCanDivide = mpCellCycleModel->ReadyToDivide(); 00384 00385 return mCanDivide; 00386 } 00387 00388 CellPtr Cell::Divide() 00389 { 00390 // Check we're allowed to divide 00391 assert(!IsDead()); 00392 assert(mCanDivide); 00393 mCanDivide = false; 00394 00395 // Reset properties of parent cell 00396 mpCellCycleModel->ResetForDivision(); 00397 00398 // Create copy of cell property collection to modify for daughter cell 00399 CellPropertyCollection daughter_property_collection = mCellPropertyCollection; 00400 00401 // Remove the CellId from the daughter cell a new one will be assigned in the constructor 00402 daughter_property_collection.RemoveProperty<CellId>(); 00403 00404 // Copy all cell data (note we create a new object not just copying the pointer) 00405 assert(daughter_property_collection.HasPropertyType<CellData>()); 00406 // Get the existing copy of the cell data and remove it from the daughter cell 00407 boost::shared_ptr<CellData> p_cell_data = GetCellData(); 00408 daughter_property_collection.RemoveProperty(p_cell_data); 00409 // Create a new cell data object using the copy constructor and add this to the daughter cell 00410 MAKE_PTR_ARGS(CellData, p_daughter_cell_data, (*p_cell_data)); 00411 daughter_property_collection.AddProperty(p_daughter_cell_data); 00412 00413 // Create daughter cell with modified cell property collection 00414 CellPtr p_new_cell(new Cell(GetMutationState(), mpCellCycleModel->CreateCellCycleModel(), false, daughter_property_collection)); 00415 // Initialise properties of daughter cell 00416 p_new_cell->SetCellProliferativeType(mCellProliferativeType); 00417 p_new_cell->GetCellCycleModel()->InitialiseDaughterCell(); 00418 00419 00420 return p_new_cell; 00421 }