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 "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)