Chaste Release::3.1
Cell.cpp
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 }