Chaste Release::3.1
CryptSimulation2d.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 "CryptSimulation2d.hpp"
00037 #include "WntConcentration.hpp"
00038 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisOne.hpp"
00039 #include "VanLeeuwen2009WntSwatCellCycleModelHypothesisTwo.hpp"
00040 #include "SmartPointers.hpp"
00041 
00042 CryptSimulation2d::CryptSimulation2d(AbstractCellPopulation<2>& rCellPopulation,
00043                                      bool deleteCellPopulationInDestructor,
00044                                      bool initialiseCells)
00045     : OffLatticeSimulation<2>(rCellPopulation,
00046                              deleteCellPopulationInDestructor,
00047                              initialiseCells),
00048       mWriteBetaCatenin(false),
00049       mUsingMeshBasedCellPopulation(false)
00050 {
00051     /* Throw an exception message if not using a  MeshBasedCellPopulation or a VertexBasedCellPopulation.
00052      * This is to catch NodeBasedCellPopulations as AbstactOnLatticeBasedCellPopulations are caught in
00053      * the OffLatticeSimulation constructor.
00054      */
00055     if ( (dynamic_cast<VertexBasedCellPopulation<2>*>(&rCellPopulation) == NULL)
00056          &&(dynamic_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation) == NULL) )
00057     {
00058         EXCEPTION("CryptSimulation2d is to be used with MeshBasedCellPopulation or VertexBasedCellPopulation (or subclasses) only");
00059     }
00060 
00061     if (dynamic_cast<MeshBasedCellPopulation<2>*>(&mrCellPopulation))
00062     {
00063         mUsingMeshBasedCellPopulation = true;
00064     }
00065 
00066     /*
00067      * To check if beta-catenin results will be written to file, we test if the first
00068      * cell has a cell-cycle model that is a subclass of AbstractVanLeeuwen2009WntSwatCellCycleModel.
00069      * In doing so, we assume that all cells in the simulation have the same cell cycle
00070      * model.
00071      */
00072     if (dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(mrCellPopulation.Begin()->GetCellCycleModel()))
00073     {
00074         mWriteBetaCatenin = true;
00075     }
00076 
00077     if (!mDeleteCellPopulationInDestructor)
00078     {
00079         // Pass a CryptSimulationBoundaryCondition object into mBoundaryConditions
00080         MAKE_PTR_ARGS(CryptSimulationBoundaryCondition<2>, p_bc, (&rCellPopulation));
00081         AddCellPopulationBoundaryCondition(p_bc);
00082     }
00083 }
00084 
00085 CryptSimulation2d::~CryptSimulation2d()
00086 {
00087 }
00088 
00089 c_vector<double, 2> CryptSimulation2d::CalculateCellDivisionVector(CellPtr pParentCell)
00090 {
00091     if (mUsingMeshBasedCellPopulation)
00092     {
00093         // Location of parent and daughter cells
00094         c_vector<double, 2> parent_coords = mrCellPopulation.GetLocationOfCellCentre(pParentCell);
00095         c_vector<double, 2> daughter_coords;
00096 
00097         // Get separation parameter
00098         double separation =
00099             static_cast<MeshBasedCellPopulation<2>*>(&mrCellPopulation)->GetMeinekeDivisionSeparation();
00100 
00101         // Make a random direction vector of the required length
00102         c_vector<double, 2> random_vector;
00103 
00104         /*
00105          * Pick a random direction and move the parent cell backwards by 0.5*separation
00106          * in that direction and return the position of the daughter cell 0.5*separation
00107          * forwards in that direction.
00108          */
00109         double random_angle = RandomNumberGenerator::Instance()->ranf();
00110         random_angle *= 2.0*M_PI;
00111 
00112         random_vector(0) = 0.5*separation*cos(random_angle);
00113         random_vector(1) = 0.5*separation*sin(random_angle);
00114 
00115         c_vector<double, 2> proposed_new_parent_coords = parent_coords - random_vector;
00116         c_vector<double, 2> proposed_new_daughter_coords = parent_coords + random_vector;
00117 
00118         if ((proposed_new_parent_coords(1) >= 0.0) && (proposed_new_daughter_coords(1) >= 0.0))
00119         {
00120             // We are not too close to the bottom of the cell population, so move parent
00121             parent_coords = proposed_new_parent_coords;
00122             daughter_coords = proposed_new_daughter_coords;
00123         }
00124         else
00125         {
00126             proposed_new_daughter_coords = parent_coords + 2.0*random_vector;
00127             while (proposed_new_daughter_coords(1) < 0.0)
00128             {
00129                 random_angle = RandomNumberGenerator::Instance()->ranf();
00130                 random_angle *= 2.0*M_PI;
00131 
00132                 random_vector(0) = separation*cos(random_angle);
00133                 random_vector(1) = separation*sin(random_angle);
00134                 proposed_new_daughter_coords = parent_coords + random_vector;
00135             }
00136             daughter_coords = proposed_new_daughter_coords;
00137         }
00138 
00139         assert(daughter_coords(1) >= 0.0); // to make sure dividing cells stay in the cell population
00140         assert(parent_coords(1) >= 0.0);   // to make sure dividing cells stay in the cell population
00141 
00142         // Set the parent to use this location
00143         ChastePoint<2> parent_coords_point(parent_coords);
00144 
00145         unsigned node_index = mrCellPopulation.GetLocationIndexUsingCell(pParentCell);
00146         mrCellPopulation.SetNode(node_index, parent_coords_point);
00147 
00148         return daughter_coords;
00149     }
00150     else // using a VertexBasedCellPopulation
00151     {
00152         c_vector<double, 2> axis_of_division = zero_vector<double>(2);
00153 
00154         // We don't need to prescribe how 'stem' cells divide if Wnt is present
00155         bool is_wnt_included = WntConcentration<2>::Instance()->IsWntSetUp();
00156         if (!is_wnt_included)
00157         {
00158             WntConcentration<2>::Destroy();
00159             if (pParentCell->GetCellProliferativeType() == STEM)
00160             {
00161                 axis_of_division(0) = 1.0;
00162                 axis_of_division(1) = 0.0;
00163             }
00164         }
00165         return axis_of_division;
00166     }
00167 }
00168 
00169 void CryptSimulation2d::SetupWriteBetaCatenin()
00170 {
00171     OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);
00172     mVizBetaCateninResultsFile = output_file_handler.OpenOutputFile("results.vizbetacatenin");
00173     *mpVizSetupFile << "BetaCatenin\n";
00174 }
00175 
00176 void CryptSimulation2d::WriteBetaCatenin(double time)
00177 {
00178     *mVizBetaCateninResultsFile <<  time << "\t";
00179 
00180     for (AbstractCellPopulation<2>::Iterator cell_iter = mrCellPopulation.Begin();
00181          cell_iter != mrCellPopulation.End();
00182          ++cell_iter)
00183     {
00184         unsigned global_index = mrCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00185         double x = mrCellPopulation.GetLocationOfCellCentre(*cell_iter)[0];
00186         double y = mrCellPopulation.GetLocationOfCellCentre(*cell_iter)[1];
00187 
00188         // We should only be calling this code block if mWriteBetaCatenin has been set to true in the constructor
00189         assert(mWriteBetaCatenin);
00190 
00191         AbstractVanLeeuwen2009WntSwatCellCycleModel* p_model = dynamic_cast<AbstractVanLeeuwen2009WntSwatCellCycleModel*>(cell_iter->GetCellCycleModel());
00192         double b_cat_membrane = p_model->GetMembraneBoundBetaCateninLevel();
00193         double b_cat_cytoplasm = p_model->GetCytoplasmicBetaCateninLevel();
00194         double b_cat_nuclear = p_model->GetNuclearBetaCateninLevel();
00195 
00196         *mVizBetaCateninResultsFile << global_index << " " << x << " " << y << " " << b_cat_membrane << " " << b_cat_cytoplasm << " " << b_cat_nuclear << " ";
00197     }
00198 
00199     *mVizBetaCateninResultsFile << "\n";
00200 }
00201 
00202 void CryptSimulation2d::SetupSolve()
00203 {
00204     // First call method on base class
00205     OffLatticeSimulation<2>::SetupSolve();
00206 
00207     /*
00208      * If there are any cells in the simulation, and mWriteBetaCatenin has been set
00209      * to true in the constructor, then set up the beta-catenin results file and
00210      * write the initial conditions to file.
00211      */
00212     bool any_cells_present = (mrCellPopulation.Begin() != mrCellPopulation.End());
00213     if (any_cells_present && mWriteBetaCatenin)
00214     {
00215         SetupWriteBetaCatenin();
00216         double current_time = SimulationTime::Instance()->GetTime();
00217         WriteBetaCatenin(current_time);
00218     }
00219 }
00220 
00221 void CryptSimulation2d::UpdateAtEndOfTimeStep()
00222 {
00223     SimulationTime* p_time = SimulationTime::Instance();
00224 
00225     if ((p_time->GetTimeStepsElapsed()+1)%mSamplingTimestepMultiple == 0)
00226     {
00227         /*
00228          * If there are any cells in the simulation, and mWriteBetaCatenin has been set
00229          * to true in the constructor, then set up the beta-catenin results file and
00230          * write the initial conditions to file.
00231          */
00232         bool any_cells_present = (mrCellPopulation.Begin() != mrCellPopulation.End());
00233         if (any_cells_present && mWriteBetaCatenin)
00234         {
00235             double time_next_step = p_time->GetTime() + p_time->GetTimeStep();
00236             WriteBetaCatenin(time_next_step);
00237         }
00238     }
00239 }
00240 
00241 void CryptSimulation2d::UpdateAtEndOfSolve()
00242 {
00243     // First call method on base class
00244     OffLatticeSimulation<2>::UpdateAtEndOfSolve();
00245 
00246     /*
00247      * If there are any cells in the simulation, and mWriteBetaCatenin has been set
00248      * to true in the constructor, then close the beta-catenin results file.
00249      */
00250     bool any_cells_present = (mrCellPopulation.Begin() != mrCellPopulation.End());
00251     if (any_cells_present && mWriteBetaCatenin)
00252     {
00253         mVizBetaCateninResultsFile->close();
00254     }
00255 }
00256 
00257 void CryptSimulation2d::UseJiggledBottomCells()
00258 {
00259     // The CryptSimulationBoundaryCondition object is the first element of mBoundaryConditions
00260     boost::static_pointer_cast<CryptSimulationBoundaryCondition<2> >(mBoundaryConditions[0])->SetUseJiggledBottomCells(true);
00261 }
00262 
00263 void CryptSimulation2d::SetBottomCellAncestors()
00264 {
00265     /*
00266      * We use a different height threshold depending on which type of cell
00267      * population we are using, a MeshBasedCellPopulationWithGhostNodes or
00268      * a VertexBasedCellPopulation.
00269      */
00270     double threshold_height = 1.0;
00271     if (mUsingMeshBasedCellPopulation)
00272     {
00273         threshold_height = 0.5;
00274     }
00275 
00276     unsigned index = 0;
00277     for (AbstractCellPopulation<2>::Iterator cell_iter = mrCellPopulation.Begin();
00278          cell_iter != mrCellPopulation.End();
00279          ++cell_iter)
00280     {
00281         if (mrCellPopulation.GetLocationOfCellCentre(*cell_iter)[1] < threshold_height)
00282         {
00283             MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (index++));
00284             cell_iter->SetAncestor(p_cell_ancestor);
00285         }
00286     }
00287 }
00288 
00289 void CryptSimulation2d::OutputSimulationParameters(out_stream& rParamsFile)
00290 {
00291     double width = mrCellPopulation.GetWidth(0);
00292     bool use_jiggled_bottom_cells = boost::static_pointer_cast<CryptSimulationBoundaryCondition<2> >(mBoundaryConditions[0])->GetUseJiggledBottomCells();
00293 
00294     *rParamsFile << "\t\t<CryptCircumference>" << width << "</CryptCircumference>\n";
00295     *rParamsFile << "\t\t<UseJiggledBottomCells>" << use_jiggled_bottom_cells << "</UseJiggledBottomCells>\n";
00296 
00297     // Call method on direct parent class
00298     OffLatticeSimulation<2>::OutputSimulationParameters(rParamsFile);
00299 }
00300 
00301 // Serialization for Boost >= 1.36
00302 #include "SerializationExportWrapperForCpp.hpp"
00303 CHASTE_CLASS_EXPORT(CryptSimulation2d)