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