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