00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "NodeBasedCellPopulation.hpp"
00029 #include "CellwiseData.hpp"
00030 #include "VtkMeshWriter.hpp"
00031
00032 template<unsigned DIM>
00033 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const std::vector<Node<DIM>* > nodes,
00034 std::vector<CellPtr>& rCells,
00035 const std::vector<unsigned> locationIndices,
00036 bool deleteNodes)
00037 : AbstractCentreBasedCellPopulation<DIM>(rCells, locationIndices),
00038 mNodes(nodes.begin(), nodes.end()),
00039 mAddedNodes(true),
00040 mpBoxCollection(NULL),
00041 mDeleteNodes(deleteNodes),
00042 mMechanicsCutOffLength(DBL_MAX)
00043 {
00044 Validate();
00045 }
00046
00047
00048 template<unsigned DIM>
00049 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const std::vector<Node<DIM>* > nodes, double mechanicsCutOffLength, bool deleteNodes)
00050 : AbstractCentreBasedCellPopulation<DIM>(),
00051 mNodes(nodes.begin(), nodes.end()),
00052 mAddedNodes(true),
00053 mpBoxCollection(NULL),
00054 mDeleteNodes(deleteNodes),
00055 mMechanicsCutOffLength(mechanicsCutOffLength)
00056 {
00057
00058 }
00059
00060 template<unsigned DIM>
00061 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const AbstractMesh<DIM,DIM>& rMesh,
00062 std::vector<CellPtr>& rCells)
00063 : AbstractCentreBasedCellPopulation<DIM>(rCells),
00064 mAddedNodes(false),
00065 mpBoxCollection(NULL),
00066 mDeleteNodes(true),
00067 mMechanicsCutOffLength(DBL_MAX)
00068 {
00069 unsigned num_nodes = rMesh.GetNumNodes();
00070
00071 mNodes.reserve(num_nodes);
00072
00073 for (unsigned i=0; i<num_nodes; i++)
00074 {
00075 Node<DIM>* p_node = new Node<DIM>(*(rMesh.GetNode(i)));
00076 mNodes.push_back(p_node);
00077 }
00078 mAddedNodes = true;
00079 Validate();
00080 }
00081
00082 template<unsigned DIM>
00083 NodeBasedCellPopulation<DIM>::~NodeBasedCellPopulation()
00084 {
00085 Clear();
00086
00087
00088 if (mDeleteNodes)
00089 {
00090 for (unsigned i=0; i<mNodes.size(); i++)
00091 {
00092 delete mNodes[i];
00093 }
00094 }
00095 }
00096
00097 template<unsigned DIM>
00098 void NodeBasedCellPopulation<DIM>::Clear()
00099 {
00100 delete mpBoxCollection;
00101 mpBoxCollection = NULL;
00102 mNodePairs.clear();
00103 mDeletedNodeIndices.clear();
00104 mAddedNodes = false;
00105 }
00106
00107 template<unsigned DIM>
00108 void NodeBasedCellPopulation<DIM>::Validate()
00109 {
00110 std::vector<bool> validated_node(GetNumNodes());
00111 for (unsigned i=0; i<validated_node.size(); i++)
00112 {
00113 validated_node[i] = false;
00114 }
00115
00116 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00117 {
00118 unsigned node_index = this->mCellLocationMap[(*cell_iter).get()];
00119 validated_node[node_index] = true;
00120 }
00121
00122 for (unsigned i=0; i<validated_node.size(); i++)
00123 {
00124 if (!validated_node[i])
00125 {
00126 std::stringstream ss;
00127 ss << "Node " << i << " does not appear to have a cell associated with it";
00128 EXCEPTION(ss.str());
00129 }
00130 }
00131 }
00132
00133 template<unsigned DIM>
00134 std::vector<Node<DIM>* >& NodeBasedCellPopulation<DIM>::rGetNodes()
00135 {
00136 return mNodes;
00137 }
00138
00139 template<unsigned DIM>
00140 const std::vector<Node<DIM>* >& NodeBasedCellPopulation<DIM>::rGetNodes() const
00141 {
00142 return mNodes;
00143 }
00144
00145 template<unsigned DIM>
00146 void NodeBasedCellPopulation<DIM>::SplitUpIntoBoxes(double cutOffLength, c_vector<double, 2*DIM> domainSize)
00147 {
00148 mpBoxCollection = new BoxCollection<DIM>(cutOffLength, domainSize);
00149 mpBoxCollection->SetupLocalBoxesHalfOnly();
00150
00151 for (unsigned i=0; i<mNodes.size(); i++)
00152 {
00153 unsigned box_index = mpBoxCollection->CalculateContainingBox(mNodes[i]);
00154 mpBoxCollection->rGetBox(box_index).AddNode(mNodes[i]);
00155 }
00156 }
00157
00158 template<unsigned DIM>
00159 void NodeBasedCellPopulation<DIM>::FindMaxAndMin()
00160 {
00161 c_vector<double, DIM> min_posn;
00162 c_vector<double, DIM> max_posn;
00163 for (unsigned i=0; i<DIM; i++)
00164 {
00165 min_posn(i) = DBL_MAX;
00166 max_posn(i) = -DBL_MAX;
00167 }
00168
00169 for (unsigned i=0; i<mNodes.size(); i++)
00170 {
00171 c_vector<double, DIM> posn = this->GetNode(i)->rGetLocation();
00172
00173 for (unsigned j=0; j<DIM; j++)
00174 {
00175 if (posn(j) > max_posn(j))
00176 {
00177 max_posn(j) = posn(j);
00178 }
00179 if (posn(j) < min_posn(j))
00180 {
00181 min_posn(j) = posn(j);
00182 }
00183 }
00184 }
00185
00186 for (unsigned i=0; i<DIM; i++)
00187 {
00188 assert(min_posn(i) != DBL_MAX);
00189 mMinSpatialPositions(i) = min_posn(i);
00190
00191 assert(max_posn(i) != -DBL_MAX);
00192 mMaxSpatialPositions(i) = max_posn(i);
00193 }
00194 }
00195
00196 template<unsigned DIM>
00197 Node<DIM>* NodeBasedCellPopulation<DIM>::GetNode(unsigned index)
00198 {
00199 return mNodes[index];
00200 }
00201
00202 template<unsigned DIM>
00203 void NodeBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00204 {
00205 mNodes[nodeIndex]->SetPoint(rNewLocation);
00206 }
00207
00208 template<unsigned DIM>
00209 void NodeBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00210 {
00211 if (hasHadBirthsOrDeaths)
00212 {
00213
00214 std::vector<Node<DIM>*> old_nodes;
00215 old_nodes.reserve(mNodes.size());
00216
00217
00218 for (unsigned i=0; i<mNodes.size(); i++)
00219 {
00220 if (!mNodes[i]->IsDeleted())
00221 {
00222 old_nodes.push_back(mNodes[i]);
00223 }
00224 else
00225 {
00226
00227 delete mNodes[i];
00228 }
00229 }
00230
00231 std::map<unsigned,CellPtr> old_map = this->mLocationCellMap;
00232 mNodes.clear();
00233
00234
00235 this->mLocationCellMap.clear();
00236 this->mCellLocationMap.clear();
00237
00238
00239 for (unsigned i=0; i<old_nodes.size(); i++)
00240 {
00241
00242 CellPtr p_live_cell = old_map[old_nodes[i]->GetIndex()];
00243
00244
00245 mNodes.push_back(old_nodes[i]);
00246 mNodes[i]->SetIndex(i);
00247
00248
00249 this->mLocationCellMap[i] = p_live_cell;
00250 this->mCellLocationMap[p_live_cell.get()] = i;
00251 }
00252
00253
00254 Clear();
00255
00256 Validate();
00257 }
00258
00259 if (mpBoxCollection!=NULL)
00260 {
00261 delete mpBoxCollection;
00262 }
00263
00264 FindMaxAndMin();
00265
00266
00267 c_vector<double, 2*DIM> domain_size;
00268
00269 for (unsigned i=0; i<DIM; i++)
00270 {
00271 domain_size(2*i) = mMinSpatialPositions(i);
00272 domain_size(2*i+1) = mMaxSpatialPositions(i);
00273 }
00274
00275 if (mMechanicsCutOffLength == DBL_MAX)
00276 {
00277 std::string error = std::string("NodeBasedCellPopulation cannot create boxes if the cut-off length has not been set - ")
00278 + std::string("Call SetMechanicsCutOffLength on the CellPopulation ensuring it is larger than GetCutOffLength() on the force law");
00279 EXCEPTION(error);
00280 }
00281
00282
00283
00284 SplitUpIntoBoxes(mMechanicsCutOffLength, domain_size);
00285
00286 mpBoxCollection->CalculateNodePairs(mNodes, mNodePairs);
00287 }
00288
00289 template<unsigned DIM>
00290 unsigned NodeBasedCellPopulation<DIM>::RemoveDeadCells()
00291 {
00292 unsigned num_removed = 0;
00293
00294 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00295 cell_iter != this->mCells.end();
00296 ++cell_iter)
00297 {
00298 if ((*cell_iter)->IsDead())
00299 {
00300
00301 num_removed++;
00302 this->GetNodeCorrespondingToCell(*cell_iter)->MarkAsDeleted();
00303 mDeletedNodeIndices.push_back(this->mCellLocationMap[(*cell_iter).get()]);
00304 cell_iter = this->mCells.erase(cell_iter);
00305 --cell_iter;
00306 }
00307 }
00308 return num_removed;
00309 }
00310
00311 template<unsigned DIM>
00312 unsigned NodeBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00313 {
00314 if (mDeletedNodeIndices.empty())
00315 {
00316 pNewNode->SetIndex(mNodes.size());
00317 mNodes.push_back(pNewNode);
00318 }
00319 else
00320 {
00321 unsigned index = mDeletedNodeIndices.back();
00322 pNewNode->SetIndex(index);
00323 mDeletedNodeIndices.pop_back();
00324 delete mNodes[index];
00325 mNodes[index] = pNewNode;
00326 }
00327 mAddedNodes = true;
00328 return pNewNode->GetIndex();
00329 }
00330
00331 template<unsigned DIM>
00332 unsigned NodeBasedCellPopulation<DIM>::GetNumNodes()
00333 {
00334 return mNodes.size() - mDeletedNodeIndices.size();
00335 }
00336
00337 template<unsigned DIM>
00338 BoxCollection<DIM>* NodeBasedCellPopulation<DIM>::GetBoxCollection()
00339 {
00340 return mpBoxCollection;
00341 }
00342
00343 template<unsigned DIM>
00344 std::set< std::pair<Node<DIM>*, Node<DIM>* > >& NodeBasedCellPopulation<DIM>::rGetNodePairs()
00345 {
00346 if (mNodePairs.empty())
00347 {
00348 EXCEPTION("No node pairs set up, rGetNodePairs probably called before Update");
00349 }
00350 return mNodePairs;
00351 }
00352
00353 template<unsigned DIM>
00354 void NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00355 {
00356 *rParamsFile << "\t\t<MechanicsCutOffLength>" << mMechanicsCutOffLength << "</MechanicsCutOffLength>\n";
00357
00358
00359
00360
00361 AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00362 }
00363
00364 template<unsigned DIM>
00365 void NodeBasedCellPopulation<DIM>::SetMechanicsCutOffLength(double mechanicsCutOffLength)
00366 {
00367 assert(mechanicsCutOffLength > 0.0);
00368 mMechanicsCutOffLength = mechanicsCutOffLength;
00369 }
00370
00371 template<unsigned DIM>
00372 double NodeBasedCellPopulation<DIM>::GetMechanicsCutOffLength()
00373 {
00374 return mMechanicsCutOffLength;
00375 }
00376
00377 template<unsigned DIM>
00378 double NodeBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00379 {
00380
00381 FindMaxAndMin();
00382
00383
00384 double width = mMaxSpatialPositions(rDimension) - mMinSpatialPositions(rDimension);
00385
00386 return width;
00387 }
00388
00389 template<unsigned DIM>
00390 void NodeBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00391 {
00392 #ifdef CHASTE_VTK
00393 std::stringstream time;
00394 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00395 VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00396
00397 unsigned num_nodes = GetNumNodes();
00398 std::vector<double> cell_types(num_nodes);
00399 std::vector<double> cell_ancestors(num_nodes);
00400 std::vector<double> cell_mutation_states(num_nodes);
00401 std::vector<double> cell_ages(num_nodes);
00402 std::vector<double> cell_cycle_phases(num_nodes);
00403 std::vector<std::vector<double> > cellwise_data;
00404
00405 if (CellwiseData<DIM>::Instance()->IsSetUp())
00406 {
00407 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00408 unsigned num_variables = p_data->GetNumVariables();
00409 for (unsigned var=0; var<num_variables; var++)
00410 {
00411 std::vector<double> cellwise_data_var(num_nodes);
00412 cellwise_data.push_back(cellwise_data_var);
00413 }
00414 }
00415
00416
00417 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00418 cell_iter != this->End();
00419 ++cell_iter)
00420 {
00421
00422 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00423
00424 if (this->mOutputCellAncestors)
00425 {
00426 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
00427 cell_ancestors[node_index] = ancestor_index;
00428 }
00429 if (this->mOutputCellProliferativeTypes)
00430 {
00431 double cell_type = cell_iter->GetCellCycleModel()->GetCellProliferativeType();
00432 cell_types[node_index] = cell_type;
00433 }
00434 if (this->mOutputCellMutationStates)
00435 {
00436 double mutation_state = cell_iter->GetMutationState()->GetColour();
00437 cell_mutation_states[node_index] = mutation_state;
00438 }
00439 if (this->mOutputCellAges)
00440 {
00441 double age = cell_iter->GetAge();
00442 cell_ages[node_index] = age;
00443 }
00444 if (this->mOutputCellCyclePhases)
00445 {
00446 double cycle_phase = cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase();
00447 cell_cycle_phases[node_index] = cycle_phase;
00448 }
00449 if (CellwiseData<DIM>::Instance()->IsSetUp())
00450 {
00451 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00452 unsigned num_variables = p_data->GetNumVariables();
00453 for (unsigned var=0; var<num_variables; var++)
00454 {
00455 cellwise_data[var][node_index] = p_data->GetValue(*cell_iter, var);
00456 }
00457 }
00458 }
00459
00460 if (this->mOutputCellProliferativeTypes)
00461 {
00462 mesh_writer.AddPointData("Cell types", cell_types);
00463 }
00464 if (this->mOutputCellAncestors)
00465 {
00466 mesh_writer.AddPointData("Ancestors", cell_ancestors);
00467 }
00468 if (this->mOutputCellMutationStates)
00469 {
00470 mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00471 }
00472 if (this->mOutputCellAges)
00473 {
00474 mesh_writer.AddPointData("Ages", cell_ages);
00475 }
00476 if (this->mOutputCellCyclePhases)
00477 {
00478 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
00479 }
00480 if (CellwiseData<DIM>::Instance()->IsSetUp())
00481 {
00482 for (unsigned var=0; var<cellwise_data.size(); var++)
00483 {
00484 std::stringstream data_name;
00485 data_name << "Cellwise data " << var;
00486 std::vector<double> cellwise_data_var = cellwise_data[var];
00487 mesh_writer.AddPointData(data_name.str(), cellwise_data_var);
00488 }
00489 }
00490
00491 {
00492
00493 TetrahedralMesh<DIM,DIM> mesh;
00494 mesh.ConstructNodesWithoutMesh(mNodes);
00495 mesh_writer.WriteFilesUsingMesh(mesh);
00496 }
00497 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00498 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00499 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00500 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00501 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00502 #endif //CHASTE_VTK
00503 }
00504
00505 template<unsigned DIM>
00506 void NodeBasedCellPopulation<DIM>::SetOutputCellVolumes(bool outputCellVolumes)
00507 {
00508 if (outputCellVolumes)
00509 {
00510 EXCEPTION("This method currently not implemented for a NodeBasedCellPopulation");
00511 }
00512 }
00513
00515
00517
00518 template class NodeBasedCellPopulation<1>;
00519 template class NodeBasedCellPopulation<2>;
00520 template class NodeBasedCellPopulation<3>;
00521
00522
00523 #include "SerializationExportWrapperForCpp.hpp"
00524 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)