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 "UblasCustomFunctions.hpp"
00030 #include "HeartConfig.hpp"
00031 #include "PostProcessingWriter.hpp"
00032 #include "PetscTools.hpp"
00033 #include "OutputFileHandler.hpp"
00034 #include "DistanceMapCalculator.hpp"
00035 #include "PseudoEcgCalculator.hpp"
00036 #include "Version.hpp"
00037 #include "HeartEventHandler.hpp"
00038
00039 #include <iostream>
00040
00041 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00042 PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::PostProcessingWriter(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00043 std::string directory,
00044 std::string hdf5File,
00045 bool makeAbsolute,
00046 std::string voltageName)
00047 : mDirectory(directory),
00048 mHdf5File(hdf5File),
00049 mMakeAbsolute(makeAbsolute),
00050 mVoltageName(voltageName),
00051 mrMesh(rMesh)
00052 {
00053 mLo = mrMesh.GetDistributedVectorFactory()->GetLow();
00054 mHi = mrMesh.GetDistributedVectorFactory()->GetHigh();
00055 mpDataReader = new Hdf5DataReader(directory, hdf5File, makeAbsolute);
00056 mpCalculator = new PropagationPropertiesCalculator(mpDataReader,voltageName);
00057
00058 assert(mpDataReader->GetNumberOfRows() == mrMesh.GetNumNodes());
00059 }
00060
00061 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00062 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WritePostProcessingFiles()
00063 {
00064
00065
00066
00067 if (HeartConfig::Instance()->IsApdMapsRequested())
00068 {
00069 std::vector<std::pair<double,double> > apd_maps;
00070 HeartConfig::Instance()->GetApdMaps(apd_maps);
00071 for (unsigned i=0; i<apd_maps.size(); i++)
00072 {
00073 WriteApdMapFile(apd_maps[i].first, apd_maps[i].second);
00074 }
00075 }
00076
00077 if (HeartConfig::Instance()->IsUpstrokeTimeMapsRequested())
00078 {
00079 std::vector<double> upstroke_time_maps;
00080 HeartConfig::Instance()->GetUpstrokeTimeMaps(upstroke_time_maps);
00081 for (unsigned i=0; i<upstroke_time_maps.size(); i++)
00082 {
00083 WriteUpstrokeTimeMap(upstroke_time_maps[i]);
00084 }
00085 }
00086
00087 if (HeartConfig::Instance()->IsMaxUpstrokeVelocityMapRequested())
00088 {
00089 std::vector<double> upstroke_velocity_maps;
00090 HeartConfig::Instance()->GetMaxUpstrokeVelocityMaps(upstroke_velocity_maps);
00091 for (unsigned i=0; i<upstroke_velocity_maps.size(); i++)
00092 {
00093 WriteMaxUpstrokeVelocityMap(upstroke_velocity_maps[i]);
00094 }
00095 }
00096
00097 if (HeartConfig::Instance()->IsConductionVelocityMapsRequested())
00098 {
00099 std::vector<unsigned> conduction_velocity_maps;
00100 HeartConfig::Instance()->GetConductionVelocityMaps(conduction_velocity_maps);
00101
00102
00103 DistanceMapCalculator<ELEMENT_DIM, SPACE_DIM> dist_map_calculator(mrMesh);
00104
00105 for (unsigned i=0; i<conduction_velocity_maps.size(); i++)
00106 {
00107 std::vector<double> distance_map;
00108 std::vector<unsigned> origin_surface;
00109 origin_surface.push_back(conduction_velocity_maps[i]);
00110 dist_map_calculator.ComputeDistanceMap(origin_surface, distance_map);
00111 WriteConductionVelocityMap(conduction_velocity_maps[i], distance_map);
00112 }
00113 }
00114
00115 if (HeartConfig::Instance()->IsAnyNodalTimeTraceRequested())
00116 {
00117 std::vector<unsigned> requested_nodes;
00118 HeartConfig::Instance()->GetNodalTimeTraceRequested(requested_nodes);
00119 WriteVariablesOverTimeAtNodes(requested_nodes);
00120 }
00121
00122 if (HeartConfig::Instance()->IsPseudoEcgCalculationRequested())
00123 {
00124 std::vector<ChastePoint<SPACE_DIM> > electrodes;
00125 HeartConfig::Instance()->GetPseudoEcgElectrodePositions(electrodes);
00126
00127 for (unsigned i=0; i<electrodes.size(); i++)
00128 {
00129 PseudoEcgCalculator<ELEMENT_DIM,SPACE_DIM,1> calculator(mrMesh, electrodes[i], mDirectory, mHdf5File, mVoltageName, mMakeAbsolute);
00130 calculator.WritePseudoEcg();
00131 }
00132 }
00133 }
00134
00135
00136 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00137 PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::~PostProcessingWriter()
00138 {
00139 delete mpDataReader;
00140 delete mpCalculator;
00141 }
00142
00143 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00144 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteApdMapFile(double repolarisationPercentage, double threshold)
00145 {
00146 std::vector<std::vector<double> > output_data = mpCalculator->CalculateAllActionPotentialDurationsForNodeRange(repolarisationPercentage, mLo, mHi, threshold);
00147 std::stringstream filename_stream;
00148 filename_stream << "Apd_" << repolarisationPercentage << "_" << threshold << "_Map.dat";
00149 WriteGenericFile(output_data, filename_stream.str());
00150 }
00151
00152 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00153 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteUpstrokeTimeMap(double threshold)
00154 {
00155 std::vector<std::vector<double> > output_data;
00156
00157 for (unsigned node_index = mLo; node_index < mHi; node_index++)
00158 {
00159 std::vector<double> upstroke_times;
00160 try
00161 {
00162 upstroke_times = mpCalculator->CalculateUpstrokeTimes(node_index, threshold);
00163 assert(upstroke_times.size() != 0);
00164 }
00165 catch(Exception& e)
00166 {
00167 upstroke_times.push_back(0);
00168 assert(upstroke_times.size() == 1);
00169 }
00170 output_data.push_back(upstroke_times);
00171 }
00172 std::stringstream filename_stream;
00173 filename_stream << "UpstrokeTimeMap_" << threshold << ".dat";
00174 WriteGenericFile(output_data, filename_stream.str());
00175 }
00176
00177 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00178 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteMaxUpstrokeVelocityMap(double threshold)
00179 {
00180 std::vector<std::vector<double> > output_data;
00181
00182 for (unsigned node_index = mLo; node_index < mHi; node_index++)
00183 {
00184 std::vector<double> upstroke_velocities;
00185 try
00186 {
00187 upstroke_velocities = mpCalculator->CalculateAllMaximumUpstrokeVelocities(node_index, threshold);
00188 assert(upstroke_velocities.size() != 0);
00189 }
00190 catch(Exception& e)
00191 {
00192 upstroke_velocities.push_back(0);
00193 assert(upstroke_velocities.size() ==1);
00194 }
00195 output_data.push_back(upstroke_velocities);
00196 }
00197 std::stringstream filename_stream;
00198 filename_stream << "MaxUpstrokeVelocityMap_" << threshold << ".dat";
00199 WriteGenericFile(output_data, filename_stream.str());
00200 }
00201
00202 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00203 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteConductionVelocityMap(unsigned originNode, std::vector<double> distancesFromOriginNode)
00204 {
00205
00206 std::vector<std::vector<double> > output_data;
00207 for (unsigned dest_node = mLo; dest_node < mHi; dest_node++)
00208 {
00209 std::vector<double> conduction_velocities;
00210 try
00211 {
00212 conduction_velocities = mpCalculator->CalculateAllConductionVelocities(originNode, dest_node, distancesFromOriginNode[dest_node]);
00213 assert(conduction_velocities.size() != 0);
00214 }
00215 catch(Exception& e)
00216 {
00217 conduction_velocities.push_back(0);
00218 assert(conduction_velocities.size() == 1);
00219 }
00220 output_data.push_back(conduction_velocities);
00221 }
00222 std::stringstream filename_stream;
00223 filename_stream << "ConductionVelocityFromNode" << originNode << ".dat";
00224 WriteGenericFile(output_data, filename_stream.str());
00225 }
00226
00227 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00228 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteAboveThresholdDepolarisationFile(double threshold )
00229 {
00230 std::vector<std::vector<double> > output_data;
00231
00232
00233 for (unsigned node_index = mLo; node_index < mHi; node_index++)
00234 {
00235 std::vector<double> upstroke_velocities;
00236 std::vector<unsigned> above_threshold_depolarisations;
00237 std::vector<double> output_item;
00238 bool no_upstroke_occurred = false;
00239
00240 try
00241 {
00242 upstroke_velocities = mpCalculator->CalculateAllMaximumUpstrokeVelocities(node_index, threshold);
00243 assert(upstroke_velocities.size() != 0);
00244 }
00245 catch(Exception& e)
00246 {
00247 upstroke_velocities.push_back(0);
00248 assert(upstroke_velocities.size() ==1);
00249 no_upstroke_occurred = true;
00250 }
00251
00252 above_threshold_depolarisations = mpCalculator->CalculateAllAboveThresholdDepolarisations(node_index, threshold);
00253
00254
00255 unsigned total_number_of_above_threshold_depolarisations = 0;
00256 for (unsigned ead_index = 0; ead_index< above_threshold_depolarisations.size();ead_index++)
00257 {
00258 total_number_of_above_threshold_depolarisations = total_number_of_above_threshold_depolarisations + above_threshold_depolarisations[ead_index];
00259 }
00260
00261
00262 if (no_upstroke_occurred)
00263 {
00264 output_item.push_back(0);
00265 }
00266 else
00267 {
00268 output_item.push_back(upstroke_velocities.size());
00269 }
00270
00271 output_item.push_back((double) total_number_of_above_threshold_depolarisations);
00272
00273 output_data.push_back(output_item);
00274 }
00275 std::stringstream filename_stream;
00276 filename_stream << "AboveThresholdDepolarisations" << threshold << ".dat";
00277 WriteGenericFile(output_data, filename_stream.str());
00278 }
00279
00280 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00281 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteVariablesOverTimeAtNodes(std::vector<unsigned>& rNodeIndices)
00282 {
00283 std::vector<std::string> variable_names = mpDataReader->GetVariableNames();
00284
00285
00286 for (unsigned name_index=0; name_index < variable_names.size(); name_index++)
00287 {
00288 std::vector<std::vector<double> > output_data;
00289 if (PetscTools::AmMaster())
00290 {
00291
00292 output_data.resize( mpDataReader->GetUnlimitedDimensionValues().size() );
00293 for (unsigned j = 0; j < mpDataReader->GetUnlimitedDimensionValues().size(); j++)
00294 {
00295 output_data[j].resize(rNodeIndices.size());
00296 }
00297
00298 for (unsigned requested_index = 0; requested_index < rNodeIndices.size(); requested_index++)
00299 {
00300 unsigned node_index = rNodeIndices[requested_index];
00301
00302
00303 if ( (mrMesh.rGetNodePermutation().size() != 0) &&
00304 !HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() )
00305 {
00306 node_index = mrMesh.rGetNodePermutation()[ rNodeIndices[requested_index] ];
00307 }
00308
00309
00310 std::vector<double> time_series = mpDataReader->GetVariableOverTime(variable_names[name_index], node_index);
00311 assert ( time_series.size() == mpDataReader->GetUnlimitedDimensionValues().size());
00312
00313
00314 for (unsigned time_step = 0; time_step < time_series.size(); time_step++)
00315 {
00316 output_data[time_step][requested_index] = time_series[time_step];
00317 }
00318 }
00319 }
00320 std::stringstream filename_stream;
00321 filename_stream << "NodalTraces_" << variable_names[name_index] << ".dat";
00322 WriteGenericFile(output_data, filename_stream.str());
00323 }
00324 }
00325
00326 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00327 void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteGenericFile(std::vector<std::vector<double> >& rDataPayload, std::string fileName)
00328 {
00329 OutputFileHandler output_file_handler(HeartConfig::Instance()->GetOutputDirectory() + "/output", false);
00330 for (unsigned writing_process=0; writing_process<PetscTools::GetNumProcs(); writing_process++)
00331 {
00332 if(PetscTools::GetMyRank() == writing_process)
00333 {
00334 out_stream p_file=out_stream(NULL);
00335 if (PetscTools::AmMaster())
00336 {
00337
00338 p_file = output_file_handler.OpenOutputFile(fileName);
00339
00340 std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
00341 *p_file << comment;
00342 }
00343 else
00344 {
00345
00346 p_file = output_file_handler.OpenOutputFile(fileName, std::ios::app);
00347 }
00348 for (unsigned line_number=0; line_number<rDataPayload.size(); line_number++)
00349 {
00350 for (unsigned i = 0; i < rDataPayload[line_number].size(); i++)
00351 {
00352 *p_file << rDataPayload[line_number][i] << "\t";
00353 }
00354 *p_file << std::endl;
00355 }
00356 p_file->close();
00357 }
00358
00359 PetscTools::Barrier();
00360 }
00361 }
00362
00364
00366
00367 template class PostProcessingWriter<1,1>;
00368 template class PostProcessingWriter<1,2>;
00369 template class PostProcessingWriter<2,2>;
00370 template class PostProcessingWriter<1,3>;
00371
00372 template class PostProcessingWriter<3,3>;