CryptSimulation2d.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, 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 "CryptSimulation2d.hpp"
00037 #include "WntConcentration.hpp"
00038 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisOne.hpp"
00039 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisTwo.hpp"
00040 #include "CellBetaCateninWriter.hpp"
00041 #include "MeshBasedCellPopulation.hpp"
00042 #include "SmartPointers.hpp"
00043 
00044 CryptSimulation2d::CryptSimulation2d(AbstractCellPopulation<2>& rCellPopulation,
00045                                      bool deleteCellPopulationInDestructor,
00046                                      bool initialiseCells)
00047     : OffLatticeSimulation<2>(rCellPopulation,
00048                              deleteCellPopulationInDestructor,
00049                              initialiseCells),
00050       mUsingMeshBasedCellPopulation(false)
00051 {
00052     /* Throw an exception message if not using a  MeshBasedCellPopulation or a VertexBasedCellPopulation.
00053      * This is to catch NodeBasedCellPopulations as AbstactOnLatticeBasedCellPopulations are caught in
00054      * the OffLatticeSimulation constructor.
00055      */
00056     if ( (dynamic_cast<VertexBasedCellPopulation<2>*>(&rCellPopulation) == NULL)
00057          &&(dynamic_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation) == NULL) )
00058     {
00059         EXCEPTION("CryptSimulation2d is to be used with MeshBasedCellPopulation or VertexBasedCellPopulation (or subclasses) only");
00060     }
00061 
00062     if (dynamic_cast<MeshBasedCellPopulation<2>*>(&mrCellPopulation))
00063     {
00064         mUsingMeshBasedCellPopulation = true;
00065     }
00066 
00067     if (!mDeleteCellPopulationInDestructor)
00068     {
00069         // Pass a CryptSimulationBoundaryCondition object into mBoundaryConditions
00070         MAKE_PTR_ARGS(CryptSimulationBoundaryCondition<2>, p_bc, (&rCellPopulation));
00071         AddCellPopulationBoundaryCondition(p_bc);
00072     }
00073 }
00074 
00075 CryptSimulation2d::~CryptSimulation2d()
00076 {
00077 }
00078 
00079 c_vector<double, 2> CryptSimulation2d::CalculateCellDivisionVector(CellPtr pParentCell)
00080 {
00081     if (mUsingMeshBasedCellPopulation)
00082     {
00083         // Location of parent and daughter cells
00084         c_vector<double, 2> parent_coords = mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00085         c_vector<double, 2> daughter_coords;
00086 
00087         // Get separation parameter
00088         double separation =
00089             static_cast<MeshBasedCellPopulation<2>*>(&mrCellPopulation)->GetMeinekeDivisionSeparation();
00090 
00091         // Make a random direction vector of the required length
00092         c_vector<double, 2> random_vector;
00093 
00094         /*
00095          * Pick a random direction and move the parent cell backwards by 0.5*separation
00096          * in that direction and return the position of the daughter cell 0.5*separation
00097          * forwards in that direction.
00098          */
00099         double random_angle = RandomNumberGenerator::Instance()->ranf();
00100         random_angle *= 2.0*M_PI;
00101 
00102         random_vector(0) = 0.5*separation*cos(random_angle);
00103         random_vector(1) = 0.5*separation*sin(random_angle);
00104 
00105         c_vector<double, 2> proposed_new_parent_coords = parent_coords - random_vector;
00106         c_vector<double, 2> proposed_new_daughter_coords = parent_coords + random_vector;
00107 
00108         if ((proposed_new_parent_coords(1) >= 0.0) && (proposed_new_daughter_coords(1) >= 0.0))
00109         {
00110             // We are not too close to the bottom of the cell population, so move parent
00111             parent_coords = proposed_new_parent_coords;
00112             daughter_coords = proposed_new_daughter_coords;
00113         }
00114         else
00115         {
00116             proposed_new_daughter_coords = parent_coords + 2.0*random_vector;
00117             while (proposed_new_daughter_coords(1) < 0.0)
00118             {
00119                 random_angle = RandomNumberGenerator::Instance()->ranf();
00120                 random_angle *= 2.0*M_PI;
00121 
00122                 random_vector(0) = separation*cos(random_angle);
00123                 random_vector(1) = separation*sin(random_angle);
00124                 proposed_new_daughter_coords = parent_coords + random_vector;
00125             }
00126             daughter_coords = proposed_new_daughter_coords;
00127         }
00128 
00129         assert(daughter_coords(1) >= 0.0); // to make sure dividing cells stay in the cell population
00130         assert(parent_coords(1) >= 0.0);   // to make sure dividing cells stay in the cell population
00131 
00132         // Set the parent to use this location
00133         ChastePoint<2> parent_coords_point(parent_coords);
00134 
00135         unsigned node_index = mrCellPopulation.GetLocationIndexUsingCell(pParentCell);
00136         mrCellPopulation.SetNode(node_index, parent_coords_point);
00137 
00138         return daughter_coords;
00139     }
00140     else // using a VertexBasedCellPopulation
00141     {
00142         // Let's check we're a VertexBasedCellPopulation when we're in debug mode...
00143         assert(dynamic_cast<VertexBasedCellPopulation<2>*>(&(this->mrCellPopulation)));
00144 
00145         VertexBasedCellPopulation<2>* p_vertex_population = dynamic_cast<VertexBasedCellPopulation<2>*>(&(this->mrCellPopulation));
00146         c_vector<double, 2> axis_of_division = p_vertex_population->
00147                 GetVertexBasedDivisionRule()->CalculateCellDivisionVector(pParentCell, *p_vertex_population);
00148 
00149         // We don't need to prescribe how 'stem' cells divide if Wnt is present
00150         bool is_wnt_included = WntConcentration<2>::Instance()->IsWntSetUp();
00151         if (!is_wnt_included)
00152         {
00153             WntConcentration<2>::Destroy();
00154             if (pParentCell->GetCellProliferativeType()->IsType<StemCellProliferativeType>())
00155             {
00156                 axis_of_division(0) = 1.0;
00157                 axis_of_division(1) = 0.0;
00158             }
00159         }
00160         return axis_of_division;
00161     }
00162 }
00163 
00164 void CryptSimulation2d::SetupSolve()
00165 {
00166     // First call method on base class
00167     OffLatticeSimulation<2>::SetupSolve();
00168 
00169     /*
00170      * To check if beta-catenin results will be written to file, we test if the first
00171      * cell has a cell-cycle model that is a subclass of AbstractVanLeeuwen2009WntSwatCellCycleModel.
00172      * In doing so, we assume that all cells in the simulation have the same cell-cycle
00173      * model.
00174      */
00175     if (dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(this->mrCellPopulation.Begin()->GetCellCycleModel()))
00176     {
00177         mrCellPopulation.AddCellWriter<CellBetaCateninWriter>();
00178     }
00179 
00180     if (dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(mrCellPopulation.Begin()->GetCellCycleModel()))
00181     {
00182         *mpVizSetupFile << "BetaCatenin\n";
00183     }
00184 }
00185 
00186 void CryptSimulation2d::UseJiggledBottomCells()
00187 {
00188     // The CryptSimulationBoundaryCondition object is the first element of mBoundaryConditions
00189     boost::static_pointer_cast<CryptSimulationBoundaryCondition<2> >(mBoundaryConditions[0])->SetUseJiggledBottomCells(true);
00190 }
00191 
00192 void CryptSimulation2d::SetBottomCellAncestors()
00193 {
00194     /*
00195      * We use a different height threshold depending on which type of cell
00196      * population we are using, a MeshBasedCellPopulationWithGhostNodes or
00197      * a VertexBasedCellPopulation.
00198      */
00199     double threshold_height = 1.0;
00200     if (mUsingMeshBasedCellPopulation)
00201     {
00202         threshold_height = 0.5;
00203     }
00204 
00205     unsigned index = 0;
00206     for (AbstractCellPopulation<2>::Iterator cell_iter = mrCellPopulation.Begin();
00207          cell_iter != mrCellPopulation.End();
00208          ++cell_iter)
00209     {
00210         if (mrCellPopulation.GetLocationOfCellCentre(*cell_iter)[1] < threshold_height)
00211         {
00212             MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (index++));
00213             cell_iter->SetAncestor(p_cell_ancestor);
00214         }
00215     }
00216 }
00217 
00218 void CryptSimulation2d::OutputSimulationParameters(out_stream& rParamsFile)
00219 {
00220     double width = mrCellPopulation.GetWidth(0);
00221     bool use_jiggled_bottom_cells = boost::static_pointer_cast<CryptSimulationBoundaryCondition<2> >(mBoundaryConditions[0])->GetUseJiggledBottomCells();
00222 
00223     *rParamsFile << "\t\t<CryptCircumference>" << width << "</CryptCircumference>\n";
00224     *rParamsFile << "\t\t<UseJiggledBottomCells>" << use_jiggled_bottom_cells << "</UseJiggledBottomCells>\n";
00225 
00226     // Call method on direct parent class
00227     OffLatticeSimulation<2>::OutputSimulationParameters(rParamsFile);
00228 }
00229 
00230 // Serialization for Boost >= 1.36
00231 #include "SerializationExportWrapperForCpp.hpp"
00232 CHASTE_CLASS_EXPORT(CryptSimulation2d)

Generated by  doxygen 1.6.2