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
00029
00030
00031
00032
00033
00034
00035
00036 #include "HeartConfigRelatedCellFactory.hpp"
00037
00038 #include <sstream>
00039 #include "HeartGeometryInformation.hpp"
00040 #include "ChasteNodesList.hpp"
00041 #include "HeartFileFinder.hpp"
00042 #include "CellMLToSharedLibraryConverter.hpp"
00043 #include "AbstractCardiacCellInterface.hpp"
00044 #include "Warnings.hpp"
00045
00046
00047 #include "AbstractCvodeCell.hpp"
00048
00049 template<unsigned SPACE_DIM>
00050 HeartConfigRelatedCellFactory<SPACE_DIM>::HeartConfigRelatedCellFactory()
00051 : AbstractCardiacCellFactory<SPACE_DIM>(),
00052 mDefaultIonicModel(HeartConfig::Instance()->GetDefaultIonicModel())
00053 {
00054
00055 HeartConfig::Instance()->GetIonicModelRegions(mIonicModelRegions,
00056 mIonicModelsDefined);
00057
00058
00059 HeartConfig::Instance()->GetStimuli(mStimuliApplied, mStimulatedAreas);
00060
00061
00062 if (mStimuliApplied.size()==0 && (HeartConfig::Instance()->IsElectrodesPresent() == false) )
00063 {
00064 EXCEPTION("Simulation needs a stimulus (either <Stimuli> or <Electrodes>).");
00065 }
00066
00067
00068 HeartConfig::Instance()->GetCellHeterogeneities(mCellHeterogeneityAreas,
00069 mScaleFactorGks,
00070 mScaleFactorIto,
00071 mScaleFactorGkr,
00072 &mParameterSettings);
00073
00074
00075 PreconvertCellmlFiles();
00076 }
00077
00078 template<unsigned SPACE_DIM>
00079 void HeartConfigRelatedCellFactory<SPACE_DIM>::PreconvertCellmlFiles()
00080 {
00081 if (mDefaultIonicModel.Dynamic().present())
00082 {
00083 LoadDynamicModel(mDefaultIonicModel, true);
00084 }
00085 for (unsigned i=0; i<mIonicModelsDefined.size(); i++)
00086 {
00087 if (mIonicModelsDefined[i].Dynamic().present())
00088 {
00089 LoadDynamicModel(mIonicModelsDefined[i], true);
00090 }
00091 }
00092 }
00093
00094 template<unsigned SPACE_DIM>
00095 DynamicCellModelLoaderPtr HeartConfigRelatedCellFactory<SPACE_DIM>::LoadDynamicModel(
00096 const cp::ionic_model_selection_type& rModel,
00097 bool isCollective)
00098 {
00099 assert(rModel.Dynamic().present());
00100 HeartFileFinder file_finder(rModel.Dynamic()->Path());
00101 CellMLToSharedLibraryConverter converter;
00102 return converter.Convert(file_finder, isCollective);
00103 }
00104
00105 template<unsigned SPACE_DIM>
00106 HeartConfigRelatedCellFactory<SPACE_DIM>::~HeartConfigRelatedCellFactory()
00107 {
00108 }
00109
00110 template<unsigned SPACE_DIM>
00111 AbstractCardiacCellInterface* HeartConfigRelatedCellFactory<SPACE_DIM>::CreateCellWithIntracellularStimulus(
00112 boost::shared_ptr<AbstractStimulusFunction> intracellularStimulus,
00113 unsigned nodeIndex)
00114 {
00115 cp::ionic_model_selection_type ionic_model = mDefaultIonicModel;
00116
00117 for (unsigned ionic_model_region_index = 0;
00118 ionic_model_region_index < mIonicModelRegions.size();
00119 ++ionic_model_region_index)
00120 {
00121 if ( mIonicModelRegions[ionic_model_region_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00122 {
00123 ionic_model = mIonicModelsDefined[ionic_model_region_index];
00124 break;
00125 }
00126 }
00127
00128 AbstractCardiacCellInterface* p_cell = NULL;
00129
00130 if (ionic_model.Dynamic().present())
00131 {
00132 #ifndef CHASTE_CAN_CHECKPOINT_DLLS
00133 if (HeartConfig::Instance()->GetCheckpointSimulation())
00134 {
00135 EXCEPTION("Checkpointing is not compatible with dynamically loaded cell models on Boost<1.37.");
00136 }
00137 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00138
00139 DynamicCellModelLoaderPtr p_loader = LoadDynamicModel(ionic_model, false);
00140 p_cell = p_loader->CreateCell(this->mpSolver, intracellularStimulus);
00141 }
00142 else
00143 {
00144 assert(ionic_model.Hardcoded().present());
00145 switch(ionic_model.Hardcoded().get())
00146 {
00147 case(cp::ionic_models_available_type::LuoRudyI):
00148 {
00149 p_cell = new CellLuoRudy1991FromCellML(this->mpSolver, intracellularStimulus);
00150 break;
00151 }
00152
00153 case(cp::ionic_models_available_type::LuoRudyIBackwardEuler):
00154 {
00155 p_cell = new CellLuoRudy1991FromCellMLBackwardEuler(this->mpSolver, intracellularStimulus);
00156 break;
00157 }
00158
00159 case(cp::ionic_models_available_type::Fox2002):
00160 {
00161 p_cell = new CellFoxModel2002FromCellML(this->mpSolver, intracellularStimulus);
00162 break;
00163 }
00164
00165 case(cp::ionic_models_available_type::Fox2002BackwardEuler):
00166 {
00167 p_cell = new CellFoxModel2002FromCellMLBackwardEuler(this->mpSolver, intracellularStimulus);
00168 break;
00169 }
00170
00171 case(cp::ionic_models_available_type::DifrancescoNoble):
00172 {
00173 p_cell = new CellDiFrancescoNoble1985FromCellML(this->mpSolver, intracellularStimulus);
00174 break;
00175 }
00176
00177 case(cp::ionic_models_available_type::MahajanShiferaw):
00178 {
00179 p_cell = new CellMahajan2008FromCellML(this->mpSolver, intracellularStimulus);
00180 break;
00181 }
00182
00183 case(cp::ionic_models_available_type::MahajanShiferawBackwardEuler):
00184 {
00185 p_cell = new CellMahajan2008FromCellMLBackwardEuler(this->mpSolver, intracellularStimulus);
00186 break;
00187 }
00188
00189 case(cp::ionic_models_available_type::tenTusscher2006):
00190 {
00191 p_cell = new CellTenTusscher2006EpiFromCellML(this->mpSolver, intracellularStimulus);
00192 break;
00193 }
00194
00195 case(cp::ionic_models_available_type::tenTusscher2006BackwardEuler):
00196 {
00197 p_cell = new CellTenTusscher2006EpiFromCellMLBackwardEuler(this->mpSolver, intracellularStimulus);
00198 break;
00199 }
00200
00201 case(cp::ionic_models_available_type::Maleckar):
00202 {
00203 p_cell = new CellMaleckar2008FromCellML(this->mpSolver, intracellularStimulus);
00204 break;
00205 }
00206
00207 case(cp::ionic_models_available_type::HodgkinHuxley):
00208 {
00209 p_cell = new CellHodgkinHuxley1952FromCellML(this->mpSolver, intracellularStimulus);
00210 break;
00211 }
00212
00213 case(cp::ionic_models_available_type::FaberRudy2000):
00214 {
00215 p_cell = new CellFaberRudy2000FromCellML(this->mpSolver, intracellularStimulus);
00216 break;
00217 }
00218
00219 case(cp::ionic_models_available_type::FaberRudy2000Optimised):
00220 {
00221 p_cell = new CellFaberRudy2000FromCellMLOpt(this->mpSolver, intracellularStimulus);
00222 break;
00223 }
00224
00225 default:
00226 {
00227
00228 NEVER_REACHED;
00229 }
00230 }
00231 }
00232
00233
00234 try
00235 {
00236 SetCellParameters(p_cell, nodeIndex);
00237 }
00238 catch (const Exception& e)
00239 {
00240 delete p_cell;
00241 throw e;
00242 }
00243
00244 p_cell->GetLookupTableCollection();
00245
00246 return p_cell;
00247 }
00248
00249
00250 template<unsigned SPACE_DIM>
00251 void HeartConfigRelatedCellFactory<SPACE_DIM>::SetCellParameters(AbstractCardiacCellInterface* pCell,
00252 unsigned nodeIndex)
00253 {
00254
00255 for (unsigned ht_index = 0;
00256 ht_index < mCellHeterogeneityAreas.size();
00257 ++ht_index)
00258 {
00259 if ( mCellHeterogeneityAreas[ht_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00260 {
00261 try
00262 {
00263 pCell->SetParameter("ScaleFactorGks", mScaleFactorGks[ht_index]);
00264 pCell->SetParameter("ScaleFactorGkr", mScaleFactorGkr[ht_index]);
00265 pCell->SetParameter("ScaleFactorIto", mScaleFactorIto[ht_index]);
00266 }
00267 catch (const Exception&)
00268 {
00269
00270 }
00271 }
00272 }
00273
00275 if (HeartConfig::Instance()->HasDrugDose())
00276 {
00277 double drug_dose = HeartConfig::Instance()->GetDrugDose();
00278 std::map<std::string, std::pair<double, double> > ic50_values = HeartConfig::Instance()->GetIc50Values();
00279 for (std::map<std::string, std::pair<double, double> >::iterator it = ic50_values.begin();
00280 it != ic50_values.end();
00281 ++it)
00282 {
00283 const std::string param_name = it->first + "_conductance";
00284 if (dynamic_cast<AbstractUntemplatedParameterisedSystem*>(pCell)->HasParameter(param_name))
00285 {
00286 const double original_conductance = pCell->GetParameter(param_name);
00287 const double ic50 = it->second.first;
00288 const double hill = it->second.second;
00289 const double new_conductance = original_conductance/(1.0 + pow(drug_dose/ic50, hill));
00290 pCell->SetParameter(param_name, new_conductance);
00291 }
00292 else
00293 {
00294 WARNING("Cannot apply drug to cell at node " << nodeIndex << " as it has no parameter named '" << param_name << "'.");
00295 }
00296 }
00297 }
00298
00299
00300 for (unsigned ht_index = 0;
00301 ht_index < mCellHeterogeneityAreas.size();
00302 ++ht_index)
00303 {
00304 if ( mCellHeterogeneityAreas[ht_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00305 {
00306 for (std::map<std::string, double>::iterator param_it = mParameterSettings[ht_index].begin();
00307 param_it != mParameterSettings[ht_index].end();
00308 ++param_it)
00309 {
00310 pCell->SetParameter(param_it->first, param_it->second);
00311 }
00312 }
00313 }
00314 }
00315
00316
00317 template<unsigned SPACE_DIM>
00318 void HeartConfigRelatedCellFactory<SPACE_DIM>::SetCellIntracellularStimulus(AbstractCardiacCellInterface* pCell,
00319 unsigned nodeIndex)
00320 {
00321 boost::shared_ptr<MultiStimulus> node_specific_stimulus(new MultiStimulus());
00322
00323 for (unsigned stimulus_index = 0;
00324 stimulus_index < mStimuliApplied.size();
00325 ++stimulus_index)
00326 {
00327 if ( mStimulatedAreas[stimulus_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00328 {
00329 node_specific_stimulus->AddStimulus(mStimuliApplied[stimulus_index]);
00330 }
00331 }
00332 pCell->SetIntracellularStimulusFunction(node_specific_stimulus);
00333 }
00334
00335
00336 template<unsigned SPACE_DIM>
00337 AbstractCardiacCellInterface* HeartConfigRelatedCellFactory<SPACE_DIM>::CreateCardiacCellForTissueNode(Node<SPACE_DIM>* pNode)
00338 {
00339 boost::shared_ptr<MultiStimulus> node_specific_stimulus(new MultiStimulus());
00340
00341
00342 for (unsigned stimulus_index = 0;
00343 stimulus_index < mStimuliApplied.size();
00344 ++stimulus_index)
00345 {
00346 if ( mStimulatedAreas[stimulus_index]->DoesContain(pNode->GetPoint()) )
00347 {
00348 node_specific_stimulus->AddStimulus(mStimuliApplied[stimulus_index]);
00349 }
00350 }
00351
00352 unsigned node_index = pNode->GetIndex();
00353 return CreateCellWithIntracellularStimulus(node_specific_stimulus, node_index);
00354 }
00355
00356 template<unsigned SPACE_DIM>
00357 void HeartConfigRelatedCellFactory<SPACE_DIM>::FillInCellularTransmuralAreas()
00358 {
00359 NEVER_REACHED;
00360 }
00361
00362 template<>
00363 void HeartConfigRelatedCellFactory<3u>::FillInCellularTransmuralAreas()
00364 {
00365 std::string mesh_file_name = HeartConfig::Instance()->GetMeshName();
00366
00367 std::string epi_surface = mesh_file_name + ".epi";
00368 std::string lv_surface = mesh_file_name + ".lv";
00369 std::string rv_surface = mesh_file_name + ".rv";
00370
00371
00372
00373
00374 HeartGeometryInformation<3u> info(*(this->GetMesh()), epi_surface, lv_surface, rv_surface, true);
00375
00376
00377 double epi_fraction = HeartConfig::Instance()->GetEpiLayerFraction();
00378 double endo_fraction = HeartConfig::Instance()->GetEndoLayerFraction();
00379
00380
00381 info.DetermineLayerForEachNode(epi_fraction,endo_fraction);
00382
00383 std::vector<unsigned> heterogeneity_node_list;
00384 for (unsigned index=0; index<this->GetMesh()->GetNumNodes(); index++)
00385 {
00386 heterogeneity_node_list.push_back(info.rGetLayerForEachNode()[index]);
00387 }
00388
00389 std::vector<Node<3u>*> epi_nodes;
00390 std::vector<Node<3u>*> mid_nodes;
00391 std::vector<Node<3u>*> endo_nodes;
00392
00393
00394 for (unsigned node_index = 0; node_index < this->GetMesh()->GetNumNodes(); node_index++)
00395 {
00396 if (this->GetMesh()->GetDistributedVectorFactory()->IsGlobalIndexLocal(node_index) )
00397 {
00398 switch (heterogeneity_node_list[node_index])
00399 {
00400
00401 case 2u:
00402 {
00403 epi_nodes.push_back(this->GetMesh()->GetNode(node_index));
00404 break;
00405 }
00406
00407 case 1u:
00408 {
00409 mid_nodes.push_back(this->GetMesh()->GetNode(node_index));
00410 break;
00411 }
00412
00413 case 0u:
00414 {
00415 endo_nodes.push_back(this->GetMesh()->GetNode(node_index));
00416 break;
00417 }
00418 default:
00419 NEVER_REACHED;
00420 }
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 unsigned user_supplied_epi_index = HeartConfig::Instance()->GetEpiLayerIndex();
00431 unsigned user_supplied_mid_index = HeartConfig::Instance()->GetMidLayerIndex();
00432 unsigned user_supplied_endo_index = HeartConfig::Instance()->GetEndoLayerIndex();
00433
00434
00435 assert(user_supplied_epi_index<3);
00436 assert(user_supplied_mid_index<3);
00437 assert(user_supplied_endo_index<3);
00438
00439
00440 std::vector<unsigned> user_supplied_indices;
00441 user_supplied_indices.push_back(user_supplied_epi_index);
00442 user_supplied_indices.push_back(user_supplied_mid_index);
00443 user_supplied_indices.push_back(user_supplied_endo_index);
00444
00445
00446
00447
00448 for (unsigned layer_index=0; layer_index<3; layer_index++)
00449 {
00450 unsigned counter = 0;
00451
00452 for (unsigned supplied_index = 0; supplied_index<user_supplied_indices.size(); supplied_index++)
00453 {
00454 if (user_supplied_indices[supplied_index] == layer_index)
00455 {
00456 break;
00457 }
00458 counter++;
00459 }
00460
00461
00462 if (counter==0)
00463 {
00464 mCellHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<3u> >(new ChasteNodesList<3u>(epi_nodes)) );
00465 }
00466 if (counter==1)
00467 {
00468 mCellHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<3u> >(new ChasteNodesList<3u>(mid_nodes)) );
00469 }
00470 if (counter==2)
00471 {
00472 mCellHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<3u> >(new ChasteNodesList<3u>(endo_nodes)) );
00473 }
00474 assert(counter<3);
00475 }
00476 assert(mCellHeterogeneityAreas.size()==3);
00477 }
00478
00479
00480 template class HeartConfigRelatedCellFactory<1u>;
00481 template class HeartConfigRelatedCellFactory<2u>;
00482 template class HeartConfigRelatedCellFactory<3u>;