Chaste Release::3.1
CryptCellsGenerator.hpp
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 #ifndef CRYPTCELLSGENERATOR_HPP_
00037 #define CRYPTCELLSGENERATOR_HPP_
00038 
00039 #include <boost/mpl/integral_c.hpp>
00040 #include <boost/type_traits/is_same.hpp>
00041 #include <boost/mpl/if.hpp>
00042 
00043 #include "CellsGenerator.hpp"
00044 
00045 #include "CellPropertyRegistry.hpp"
00046 #include "TetrahedralMesh.hpp"
00047 #include "VertexMesh.hpp"
00048 #include "PottsMesh.hpp"
00049 
00050 #include "StochasticDurationGenerationBasedCellCycleModel.hpp"
00051 #include "FixedDurationGenerationBasedCellCycleModel.hpp"
00052 #include "TysonNovakCellCycleModel.hpp"
00053 #include "WntCellCycleModel.hpp"
00054 #include "SimpleWntCellCycleModel.hpp"
00055 #include "StochasticWntCellCycleModel.hpp"
00056 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisOne.hpp"
00057 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisTwo.hpp"
00058 #include "Exception.hpp"
00059 
00060 
00065 template<class T1, class T2>
00066 bool ClassesAreSame()
00067 {
00068     using namespace boost::mpl;
00069     using namespace boost;
00070     typedef typename if_< is_same<T1, T2>, integral_c<unsigned, 1>, integral_c<unsigned, 0> >::type selector_t;
00071     return  (selector_t()==1);
00072 }
00073 
00079 template<class CELL_CYCLE_MODEL>
00080 class CryptCellsGenerator : public CellsGenerator<CELL_CYCLE_MODEL,2>
00081 {
00082 public:
00083 
00101     void Generate(std::vector<CellPtr>& rCells,
00102                   AbstractMesh<2,2>* pMesh,
00103                   const std::vector<unsigned> locationIndices,
00104                   bool randomBirthTimes,
00105                   double y0 = 0.3,
00106                   double y1 = 2.0,
00107                   double y2 = 3.0,
00108                   double y3 = 4.0,
00109                   bool initialiseCells = false);
00110 };
00111 
00112 
00113 template<class CELL_CYCLE_MODEL>
00114 void CryptCellsGenerator<CELL_CYCLE_MODEL>::Generate(
00115                                       std::vector<CellPtr>& rCells,
00116                                       AbstractMesh<2,2>* pMesh,
00117                                       const std::vector<unsigned> locationIndices,
00118                                       bool randomBirthTimes,
00119                                       double y0,
00120                                       double y1,
00121                                       double y2,
00122                                       double y3,
00123                                       bool initialiseCells)
00124 {
00125     CellPropertyRegistry::Instance()->Clear();
00126 
00127     RandomNumberGenerator* p_random_num_gen = RandomNumberGenerator::Instance();
00128 
00129     rCells.clear();
00130 
00131     unsigned mesh_size;
00132     if (dynamic_cast<TetrahedralMesh<2,2>*>(pMesh))
00133     {
00134         mesh_size = pMesh->GetNumNodes();
00135         unsigned num_cells = locationIndices.empty() ? pMesh->GetNumNodes() : locationIndices.size();
00136         rCells.reserve(num_cells);
00137     }
00138     else if (dynamic_cast<PottsMesh<2>*>(pMesh))
00139     {
00140         mesh_size = static_cast<PottsMesh<2>*>(pMesh)->GetNumElements();
00141         rCells.reserve(mesh_size);
00142     }
00143     else
00144     {
00145         /*
00146          * We cannot directly assert this dynamic cast. This is because the assert macro
00147          * doesn't understand the <2,2> and thinks that it is being passed two arguments.
00148          */
00149         bool is_vertex_mesh = (dynamic_cast<VertexMesh<2,2>*>(pMesh));
00150         if (!is_vertex_mesh)
00151         {
00152             NEVER_REACHED;
00153         }
00154         mesh_size = static_cast<VertexMesh<2,2>*>(pMesh)->GetNumElements();
00155         rCells.reserve(mesh_size);
00156     }
00157 
00158     for (unsigned i=0; i<mesh_size; i++)
00159     {
00160         CellProliferativeType cell_type;
00161         unsigned generation;
00162 
00163         double y = 0.0;
00164 
00165         if (dynamic_cast<TetrahedralMesh<2,2>*>(pMesh))
00166         {
00167             if (locationIndices.empty())
00168             {
00169                 y = pMesh->GetNode(i)->GetPoint().rGetLocation()[1];
00170 
00171             }
00172             else if (std::find(locationIndices.begin(), locationIndices.end(), i) != locationIndices.end())
00173             {
00174                 y = pMesh->GetNode(i)->GetPoint().rGetLocation()[1];
00175             }
00176         }
00177         else if (dynamic_cast<PottsMesh<2>*>(pMesh))
00178         {
00179             y = dynamic_cast<PottsMesh<2>*>(pMesh)->GetCentroidOfElement(i)[1];
00180         }
00181         else
00182         {
00183             /*
00184              * We cannot directly assert this dynamic cast. This is because the assert macro
00185              * doesn't understand the <2,2> and thinks that it is being passed two arguments.
00186              */
00187             bool is_vertex_mesh = (dynamic_cast<VertexMesh<2,2>*>(pMesh));
00188             if (!is_vertex_mesh)
00189             {
00190                 NEVER_REACHED;
00191             }
00192             y = dynamic_cast<VertexMesh<2,2>*>(pMesh)->GetCentroidOfElement(i)[1];
00193         }
00194 
00195         CELL_CYCLE_MODEL* p_cell_cycle_model = new CELL_CYCLE_MODEL;
00196         p_cell_cycle_model->SetDimension(2);
00197 
00198         double typical_transit_cycle_time = p_cell_cycle_model->GetAverageTransitCellCycleTime();
00199         double typical_stem_cycle_time = p_cell_cycle_model->GetAverageStemCellCycleTime();
00200 
00201         double birth_time = 0.0;
00202         if (randomBirthTimes)
00203         {
00204             birth_time = -p_random_num_gen->ranf();
00205         }
00206 
00207         if (y <= y0)
00208         {
00209             cell_type = STEM;
00210             generation = 0;
00211             birth_time *= typical_stem_cycle_time; // hours
00212         }
00213         else if (y < y1)
00214         {
00215             cell_type = TRANSIT;
00216             generation = 1;
00217             birth_time *= typical_transit_cycle_time; // hours
00218         }
00219         else if (y < y2)
00220         {
00221             cell_type = TRANSIT;
00222             generation = 2;
00223             birth_time *= typical_transit_cycle_time; // hours
00224         }
00225         else if (y < y3)
00226         {
00227             cell_type = TRANSIT;
00228             generation = 3;
00229             birth_time *= typical_transit_cycle_time; // hours
00230         }
00231         else
00232         {
00233             cell_type = p_cell_cycle_model->CanCellTerminallyDifferentiate() ? DIFFERENTIATED : TRANSIT;
00234             generation = 4;
00235             birth_time *= typical_transit_cycle_time; // hours
00236         }
00237 
00238         if (dynamic_cast<AbstractSimpleGenerationBasedCellCycleModel*>(p_cell_cycle_model))
00239         {
00240             dynamic_cast<AbstractSimpleGenerationBasedCellCycleModel*>(p_cell_cycle_model)->SetGeneration(generation);
00241         }
00242 
00243         boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>());
00244 
00245         CellPtr p_cell(new Cell(p_state, p_cell_cycle_model));
00246         p_cell->SetCellProliferativeType(cell_type);
00247 
00248         if (initialiseCells)
00249         {
00250             p_cell->InitialiseCellCycleModel();
00251         }
00252 
00253         p_cell->SetBirthTime(birth_time);
00254 
00255         if (locationIndices.empty())
00256         {
00257             rCells.push_back(p_cell);
00258         }
00259         else if (std::find(locationIndices.begin(), locationIndices.end(), i) != locationIndices.end())
00260         {
00261             rCells.push_back(p_cell);
00262         }
00263     }
00264 }
00265 
00266 #endif /* CRYPTCELLSGENERATOR_HPP_ */