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 #include "CellProperties.hpp"
00031 #include "Exception.hpp"
00032 #include <cmath>
00033
00034 #include <iostream>
00035
00036 enum APPhases { BELOWTHRESHOLD , ABOVETHRESHOLD };
00037
00038 void CellProperties::CalculateProperties()
00039 {
00040
00041 if (mrTime.size() < 1)
00042 {
00043 EXCEPTION("Insufficient time steps to calculate physiological properties.");
00044 }
00045
00046 double prev_v = mrVoltage[0];
00047 double prev_t = mrTime[0];
00048 double current_upstroke_velocity = 0;
00049 double current_time_of_upstroke_velocity = 0;
00050 double current_resting_value=-DBL_MAX;
00051 double current_peak=-DBL_MAX;
00052 double current_minimum_velocity=DBL_MAX;
00053 double prev_upstroke_vel=0;
00054 unsigned ap_counter = 0;
00055
00056 APPhases ap_phase = BELOWTHRESHOLD;
00057
00058 unsigned time_steps = mrTime.size()-1;
00059
00060 for (unsigned i=1; i<=time_steps; i++)
00061 {
00062 double v = mrVoltage[i];
00063 double t = mrTime[i];
00064 double upstroke_vel;
00065
00066 if (i==1)
00067 {
00068
00069 upstroke_vel = 0;
00070 }
00071 else
00072 {
00073 upstroke_vel = (v - prev_v) / (t - prev_t);
00074 }
00075
00076
00077 if(upstroke_vel>=current_upstroke_velocity)
00078 {
00079 current_upstroke_velocity = upstroke_vel;
00080 current_time_of_upstroke_velocity = t;
00081 }
00082
00083 switch (ap_phase)
00084 {
00085 case BELOWTHRESHOLD:
00086
00087
00088 if(fabs(upstroke_vel)<=current_minimum_velocity)
00089 {
00090 current_minimum_velocity=fabs(upstroke_vel);
00091 current_resting_value = v;
00092 }
00093
00094
00095 if( v>mThreshold && prev_v <= mThreshold )
00096 {
00097
00098 mRestingValues.push_back(current_resting_value);
00099 current_minimum_velocity = DBL_MAX;
00100
00101
00102 mOnsets.push_back(prev_t + (t-prev_t)/(v-prev_v)*(mThreshold-prev_v));
00103
00104
00105 if (ap_counter>0)
00106 {
00107 mCycleLengths.push_back( mOnsets[ap_counter]-mOnsets[ap_counter-1] );
00108 }
00109
00110 ap_phase = ABOVETHRESHOLD;
00111 }
00112 break;
00113
00114 case ABOVETHRESHOLD:
00115
00116 if (v>current_peak)
00117 {
00118 current_peak = v;
00119 }
00120
00121
00122
00123 if( v<mThreshold && prev_v >= mThreshold )
00124 {
00125
00126 mPeakValues.push_back(current_peak);
00127
00128 current_peak = mThreshold;
00129
00130
00131 mMaxUpstrokeVelocities.push_back(current_upstroke_velocity);
00132
00133 current_upstroke_velocity = 0.0;
00134
00135
00136 mTimesAtMaxUpstrokeVelocity.push_back(current_time_of_upstroke_velocity);
00137
00138 current_time_of_upstroke_velocity = 0.0;
00139
00140
00141 ap_counter++;
00142 ap_phase = BELOWTHRESHOLD;
00143 }
00144 break;
00145 }
00146
00147 prev_v = v;
00148 prev_t = t;
00149 prev_upstroke_vel = upstroke_vel;
00150 }
00151
00152
00153
00154
00155
00156
00157 if (mOnsets.size()>mMaxUpstrokeVelocities.size())
00158 {
00159 mMaxUpstrokeVelocities.push_back(current_upstroke_velocity);
00160 }
00161 if (mOnsets.size()>mPeakValues.size())
00162 {
00163 mPeakValues.push_back(current_peak);
00164 }
00165 if (mOnsets.size()>mTimesAtMaxUpstrokeVelocity.size())
00166 {
00167 mTimesAtMaxUpstrokeVelocity.push_back(current_time_of_upstroke_velocity);
00168 }
00169 }
00170
00171
00172 std::vector<double> CellProperties::CalculateActionPotentialDurations(const double percentage,
00173 std::vector<double>& rOnsets,
00174 std::vector<double>& rRestingPotentials,
00175 std::vector<double>& rPeakPotentials)
00176 {
00177 double prev_v = -DBL_MAX;
00178 unsigned APcounter=0;
00179 bool apd_is_calculated=true;
00180 std::vector<double> apds;
00181 double target = DBL_MAX;
00182
00183 for (unsigned i=0; i<mrTime.size(); i++)
00184 {
00185 double t = mrTime[i];
00186 double v = mrVoltage[i];
00187
00188
00189 if (APcounter<rPeakPotentials.size())
00190 {
00191
00192 target = rRestingPotentials[APcounter]+0.01*(100-percentage)*(rPeakPotentials[APcounter]-rRestingPotentials[APcounter]);
00193
00194
00195 if (fabs(v-rPeakPotentials[APcounter])<=1e-6)
00196 {
00197 apd_is_calculated=false;
00198 }
00199
00200
00201 if ( prev_v>v && prev_v>=target && v<=target && apd_is_calculated==false)
00202 {
00203 apds.push_back (t - rOnsets[APcounter]);
00204 APcounter++;
00205 apd_is_calculated=true;
00206 }
00207 }
00208 prev_v = v;
00209 }
00210
00211 return apds;
00212 }
00213
00214
00215 std::vector<double> CellProperties::GetAllActionPotentialDurations(const double percentage)
00216 {
00217 if (mOnsets.size() == 0)
00218 {
00219
00220 EXCEPTION("No action potential occurred");
00221 }
00222
00223 std::vector<double> apds = CalculateActionPotentialDurations(percentage,
00224 mOnsets,
00225 mRestingValues,
00226 mPeakValues);
00227
00228 return apds;
00229 }
00230
00231 double CellProperties::GetLastActionPotentialDuration(const double percentage)
00232 {
00233 if (mOnsets.size() == 0)
00234 {
00235
00236 EXCEPTION("No action potential occurred");
00237 }
00238
00239 std::vector<double> apds = CalculateActionPotentialDurations(percentage,
00240 mOnsets,
00241 mRestingValues,
00242 mPeakValues);
00243 if (apds.size()==0)
00244 {
00245 EXCEPTION("No complete action potential occurred");
00246 }
00247
00248
00249 return apds[apds.size()-1];
00250 }
00251
00252 std::vector<double> CellProperties::GetActionPotentialAmplitudes()
00253 {
00254 unsigned size = mPeakValues.size();
00255 std::vector<double> amplitudes(size);
00256 for (unsigned i=0; i< size ;i++)
00257 {
00258 amplitudes[i] = (mPeakValues[i] - mRestingValues[i]);
00259 }
00260 return amplitudes;
00261 }
00262 double CellProperties::GetLastMaxUpstrokeVelocity()
00263 {
00264 unsigned size = mMaxUpstrokeVelocities.size();
00265 if (size==0)
00266 {
00267 EXCEPTION("Upstroke never occurred");
00268 }
00269 return mMaxUpstrokeVelocities[size-1];
00270
00271 }
00272 double CellProperties::GetTimeAtLastMaxUpstrokeVelocity()
00273 {
00274 unsigned size = mTimesAtMaxUpstrokeVelocity.size();
00275 if (size==0)
00276 {
00277 EXCEPTION("Upstroke never occurred");
00278 }
00279 return mTimesAtMaxUpstrokeVelocity[size-1];
00280 }
00281