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 "HeartGeometryInformation.hpp"
00030
00031 #include <cmath>
00032 #include <fstream>
00033 #include <sstream>
00034 #include "OutputFileHandler.hpp"
00035 #include "Exception.hpp"
00036 #include "PetscTools.hpp"
00037
00038
00039
00040 template<unsigned SPACE_DIM>
00041 const double HeartGeometryInformation<SPACE_DIM>::LEFT_SEPTUM_SIZE = 2.0/3.0;
00042
00043 template<unsigned SPACE_DIM>
00044 const double HeartGeometryInformation<SPACE_DIM>::RIGHT_SEPTUM_SIZE = 1.0/3.0;
00045
00046 template<unsigned SPACE_DIM>
00047 HeartGeometryInformation<SPACE_DIM>::HeartGeometryInformation(TetrahedralMesh<SPACE_DIM,SPACE_DIM>& rMesh,
00048 std::string mEpiFile,
00049 std::string mEndoFile)
00050 : mrMesh(rMesh)
00051 {
00052 DistanceMapCalculator<SPACE_DIM> distance_calculator(mrMesh);
00053
00054
00055 GetNodesAtSurface(mEpiFile, mEpiSurface);
00056 GetNodesAtSurface(mEndoFile, mEndoSurface);
00057
00058
00059 distance_calculator.ComputeDistanceMap(mEpiSurface, mDistMapEpicardium);
00060 distance_calculator.ComputeDistanceMap(mEndoSurface, mDistMapEndocardium);
00061
00062 mNumberOfSurfacesProvided = 2;
00063 }
00064
00065 template<unsigned SPACE_DIM>
00066 HeartGeometryInformation<SPACE_DIM>::HeartGeometryInformation (TetrahedralMesh<SPACE_DIM,SPACE_DIM>& rMesh,
00067 std::string mEpiFile,
00068 std::string mLVFile,
00069 std::string mRVFile)
00070 : mrMesh(rMesh)
00071 {
00072 DistanceMapCalculator<SPACE_DIM> distance_calculator(mrMesh);
00073
00074
00075 GetNodesAtSurface(mEpiFile, mEpiSurface);
00076 GetNodesAtSurface(mLVFile, mLVSurface);
00077 GetNodesAtSurface(mRVFile, mRVSurface);
00078
00079
00080 distance_calculator.ComputeDistanceMap(mEpiSurface, mDistMapEpicardium);
00081 distance_calculator.ComputeDistanceMap(mLVSurface, mDistMapLeftVentricle);
00082 distance_calculator.ComputeDistanceMap(mRVSurface, mDistMapRightVentricle);
00083
00084 mNumberOfSurfacesProvided = 3;
00085 }
00086
00087 template<unsigned SPACE_DIM>
00088 HeartGeometryInformation<SPACE_DIM>::HeartGeometryInformation (TetrahedralMesh<SPACE_DIM,SPACE_DIM>& rMesh,
00089 std::vector<unsigned>& rNodesAtEpi,
00090 std::vector<unsigned>& rNodesAtEndo)
00091 : mrMesh(rMesh)
00092
00093 {
00094 DistanceMapCalculator<SPACE_DIM> distance_calculator(mrMesh);
00095
00096
00097 distance_calculator.ComputeDistanceMap(rNodesAtEpi, mDistMapEpicardium);
00098 distance_calculator.ComputeDistanceMap(rNodesAtEndo, mDistMapEndocardium);
00099
00100 mNumberOfSurfacesProvided = 2;
00101 }
00102
00103 template<unsigned SPACE_DIM>
00104 HeartGeometryInformation<SPACE_DIM>::HeartGeometryInformation (TetrahedralMesh<SPACE_DIM,SPACE_DIM>& rMesh,
00105 std::vector<unsigned>& rNodesAtEpi,
00106 std::vector<unsigned>& rNodesAtLv,
00107 std::vector<unsigned>& rNodesAtRv)
00108 : mrMesh(rMesh)
00109 {
00110 DistanceMapCalculator<SPACE_DIM> distance_calculator(mrMesh);
00111
00112
00113 distance_calculator.ComputeDistanceMap(rNodesAtEpi, mDistMapEpicardium);
00114 distance_calculator.ComputeDistanceMap(rNodesAtLv, mDistMapLeftVentricle);
00115 distance_calculator.ComputeDistanceMap(rNodesAtRv, mDistMapRightVentricle);
00116 mNumberOfSurfacesProvided = 3;
00117 }
00118
00119
00120 template<unsigned SPACE_DIM>
00121 void HeartGeometryInformation<SPACE_DIM>::ProcessLine(
00122 const std::string& line, std::set<unsigned>& surfaceNodeIndexSet) const
00123 {
00124 unsigned num_nodes = 0;
00125 std::stringstream line_stream(line);
00126
00127 while (!line_stream.eof())
00128 {
00129 unsigned item;
00130 line_stream >> item;
00131
00132 surfaceNodeIndexSet.insert(item-1);
00133
00134 num_nodes++;
00135 }
00136
00137 if (num_nodes != SPACE_DIM)
00138 {
00139 EXCEPTION("Wrong file format");
00140 }
00141
00142 }
00143
00144
00145 template<unsigned SPACE_DIM>
00146 void HeartGeometryInformation<SPACE_DIM>::GetNodesAtSurface(
00147 const std::string& surfaceFile, std::vector<unsigned>& rSurfaceNodes) const
00148 {
00149
00150 std::ifstream file_stream;
00151 file_stream.open(surfaceFile.c_str());
00152 if (!file_stream.is_open())
00153 {
00154 EXCEPTION("Wrong surface definition file name " + surfaceFile);
00155 }
00156
00157
00158 std::set<unsigned> surface_node_index_set;
00159
00160
00161 std::string line;
00162 getline(file_stream, line);
00163 do
00164 {
00165 ProcessLine(line, surface_node_index_set);
00166
00167 getline(file_stream, line);
00168 }
00169 while(!file_stream.eof());
00170
00171
00172 rSurfaceNodes.reserve(surface_node_index_set.size());
00173
00174
00175 for(std::set<unsigned>::iterator node_index_it=surface_node_index_set.begin();
00176 node_index_it != surface_node_index_set.end();
00177 node_index_it++)
00178 {
00179 rSurfaceNodes.push_back(*node_index_it);
00180 }
00181
00182 file_stream.close();
00183 }
00184
00185
00186
00187 template<unsigned SPACE_DIM>
00188 HeartRegionType HeartGeometryInformation<SPACE_DIM>::GetHeartRegion(unsigned nodeIndex) const
00189 {
00190
00191 if (mDistMapRightVentricle[nodeIndex] >= mDistMapEpicardium[nodeIndex] &&
00192 mDistMapRightVentricle[nodeIndex] >= mDistMapLeftVentricle[nodeIndex])
00193 {
00194 return HeartRegionCode::LEFT_VENTRICLE_WALL;
00195 }
00196
00197 if (mDistMapLeftVentricle[nodeIndex] >= mDistMapEpicardium[nodeIndex] &&
00198 mDistMapLeftVentricle[nodeIndex] >= mDistMapRightVentricle[nodeIndex])
00199 {
00200 return HeartRegionCode::RIGHT_VENTRICLE_WALL;
00201 }
00202
00203 if (mDistMapEpicardium[nodeIndex] >= mDistMapLeftVentricle[nodeIndex] &&
00204 mDistMapEpicardium[nodeIndex] >= mDistMapRightVentricle[nodeIndex])
00205 {
00206 if (mDistMapLeftVentricle[nodeIndex]
00207 < LEFT_SEPTUM_SIZE*(mDistMapLeftVentricle[nodeIndex] + mDistMapRightVentricle[nodeIndex]))
00208 {
00209 return HeartRegionCode::LEFT_SEPTUM;
00210 }
00211 else
00212 {
00213 return HeartRegionCode::RIGHT_SEPTUM;
00214 }
00215 }
00216
00217 return HeartRegionCode::UNKNOWN;
00218 }
00219
00220 template<unsigned SPACE_DIM>
00221 double HeartGeometryInformation<SPACE_DIM>::GetDistanceToEndo(unsigned nodeIndex)
00222 {
00223
00224 if ( mNumberOfSurfacesProvided == 3)
00225 {
00226 HeartRegionType node_region = GetHeartRegion(nodeIndex);
00227 switch(node_region)
00228 {
00229 case HeartRegionCode::LEFT_VENTRICLE_WALL:
00230 case HeartRegionCode::LEFT_VENTRICLE_SURFACE:
00231 return mDistMapLeftVentricle[nodeIndex];
00232 break;
00233
00234 case HeartRegionCode::RIGHT_VENTRICLE_WALL:
00235 case HeartRegionCode::RIGHT_VENTRICLE_SURFACE:
00236 return mDistMapRightVentricle[nodeIndex];
00237 break;
00238
00239 case HeartRegionCode::LEFT_SEPTUM:
00240 return mDistMapLeftVentricle[nodeIndex];
00241 break;
00242
00243 case HeartRegionCode::RIGHT_SEPTUM:
00244 return mDistMapRightVentricle[nodeIndex] ;
00245 break;
00246
00247 case HeartRegionCode::UNKNOWN:
00248 #define COVERAGE_IGNORE
00249 std::cerr << "Wrong distances node: " << nodeIndex << "\t"
00250 << "Epi " << mDistMapEpicardium[nodeIndex] << "\t"
00251 << "RV " << mDistMapRightVentricle[nodeIndex] << "\t"
00252 << "LV " << mDistMapLeftVentricle[nodeIndex]
00253 << std::endl;
00254
00255
00256 return 0.0;
00257 break;
00258 #undef COVERAGE_IGNORE
00259
00260 default:
00261 NEVER_REACHED;
00262 }
00263 }
00264
00265 else
00266 {
00267 return mDistMapEndocardium[nodeIndex];
00268 }
00269
00270
00271 NEVER_REACHED;
00272 return 0.0;
00273 }
00274
00275 template<unsigned SPACE_DIM>
00276 double HeartGeometryInformation<SPACE_DIM>::GetDistanceToEpi(unsigned nodeIndex)
00277 {
00279 return mDistMapEpicardium[nodeIndex];
00280 }
00281
00282 template<unsigned SPACE_DIM>
00283 double HeartGeometryInformation<SPACE_DIM>::CalculateRelativeWallPosition(unsigned nodeIndex)
00284 {
00285
00286 double dist_endo = GetDistanceToEndo(nodeIndex);
00287 double dist_epi = GetDistanceToEpi(nodeIndex);
00288
00289 double relative_position;
00290
00291 if ( (dist_endo + dist_epi) != 0 )
00292 {
00293 relative_position = dist_endo / (dist_endo + dist_epi);
00294 }
00295 else
00296 {
00297
00298
00299
00300
00301 relative_position = 0;
00302 }
00303 return relative_position;
00304 }
00305
00306 template<unsigned SPACE_DIM>
00307 void HeartGeometryInformation<SPACE_DIM>::DetermineLayerForEachNode(double epiFraction, double endoFraction)
00308 {
00309 assert(epiFraction+endoFraction<1);
00310 assert(endoFraction>0);
00311 assert(epiFraction>0);
00312
00313 mLayerForEachNode.resize(mrMesh.GetNumNodes());
00314 for(unsigned i=0; i<mrMesh.GetNumNodes(); i++)
00315 {
00316 double position = CalculateRelativeWallPosition(i);
00317 if (position<endoFraction)
00318 {
00319 mLayerForEachNode[i] = ENDO;
00320 }
00321 else if (position<(1-epiFraction))
00322 {
00323 mLayerForEachNode[i] = MID;
00324 }
00325 else
00326 {
00327 mLayerForEachNode[i] = EPI;
00328 }
00329 }
00330 }
00331
00332
00333 template<unsigned SPACE_DIM>
00334 void HeartGeometryInformation<SPACE_DIM>::WriteLayerForEachNode(std::string outputDir, std::string file)
00335 {
00336 if (PetscTools::AmMaster())
00337 {
00338 OutputFileHandler handler(outputDir,false);
00339 out_stream p_file = handler.OpenOutputFile(file);
00340
00341 assert(mLayerForEachNode.size()>0);
00342 for(unsigned i=0; i<mrMesh.GetNumNodes(); i++)
00343 {
00344 if(mLayerForEachNode[i]==EPI)
00345 {
00346 *p_file << "0\n";
00347 }
00348 else if(mLayerForEachNode[i]==MID)
00349 {
00350 *p_file << "1\n";
00351 }
00352 else
00353 {
00354 *p_file << "2\n";
00355 }
00356 }
00357
00358 p_file->close();
00359 }
00360 PetscTools::Barrier();
00361 }
00362
00363
00364
00366
00368
00369
00370 template class HeartGeometryInformation<2>;
00371 template class HeartGeometryInformation<3>;