PropagationPropertiesCalculator.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "UblasIncludes.hpp"
00030 #include "PropagationPropertiesCalculator.hpp"
00031 #include "CellProperties.hpp"
00032 #include "Exception.hpp"
00033 #include <sstream>
00034 
00035 PropagationPropertiesCalculator::PropagationPropertiesCalculator(Hdf5DataReader* pDataReader,
00036                                                                  const std::string voltageName)
00037     : mpDataReader(pDataReader),
00038       mVoltageName(voltageName),
00039       mTimes(mpDataReader->GetUnlimitedDimensionValues()),
00040       mCachedNodeGlobalIndex(UNSIGNED_UNSET)
00041 {}
00042 
00043 PropagationPropertiesCalculator::~PropagationPropertiesCalculator()
00044 {
00045     // We don't own the data reader, so we don't destroy it.
00046 }
00047 
00048 double PropagationPropertiesCalculator::CalculateMaximumUpstrokeVelocity(unsigned globalNodeIndex)
00049 {
00050     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00051     CellProperties cell_props(r_voltages, mTimes);
00052     return cell_props.GetLastMaxUpstrokeVelocity();
00053 }
00054 
00055 std::vector<double> PropagationPropertiesCalculator::CalculateAllMaximumUpstrokeVelocities(unsigned globalNodeIndex, double threshold)
00056 {
00057     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00058     CellProperties cell_props(r_voltages, mTimes, threshold);
00059     return cell_props.GetMaxUpstrokeVelocities();
00060 }
00061 
00062 std::vector<double> PropagationPropertiesCalculator::CalculateUpstrokeTimes(unsigned globalNodeIndex, double threshold)
00063 {
00064     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00065     CellProperties cell_props(r_voltages, mTimes, threshold);
00066     return cell_props.GetTimesAtMaxUpstrokeVelocity();
00067 }
00068 
00069 double PropagationPropertiesCalculator::CalculateActionPotentialDuration(const double percentage,
00070                                                                          unsigned globalNodeIndex)
00071 {
00072     if (percentage < 1.0 || percentage >= 100.0)
00073     {
00074         EXCEPTION("First argument of CalculateActionPotentialDuration() is expected to be a percentage");
00075     }
00076     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00077     CellProperties cell_props(r_voltages, mTimes);
00078     return cell_props.GetLastActionPotentialDuration(percentage);
00079 }
00080 
00081 std::vector<double> PropagationPropertiesCalculator::CalculateAllActionPotentialDurations(const double percentage,
00082                                                                                           unsigned globalNodeIndex,
00083                                                                                           double threshold)
00084 {
00085     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00086     CellProperties cell_props(r_voltages, mTimes, threshold);
00087     return cell_props.GetAllActionPotentialDurations(percentage);
00088 }
00089 
00090 double PropagationPropertiesCalculator::CalculatePeakMembranePotential(unsigned globalNodeIndex)
00091 {
00092     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00093     double max = -DBL_MAX;
00094     for (unsigned i=0; i<r_voltages.size(); i++)
00095     {
00096         if (r_voltages[i]>max)
00097         {
00098             max = r_voltages[i];
00099         }
00100     }
00101     return max;
00102 }
00103 
00104 double PropagationPropertiesCalculator::CalculateConductionVelocity(unsigned globalNearNodeIndex,
00105                                                                     unsigned globalFarNodeIndex,
00106                                                                     const double euclideanDistance)
00107 {
00108     double t_near = 0;
00109     double t_far = 0;
00110     std::vector<double>& r_near_voltages = rCacheVoltages(globalNearNodeIndex);
00111     std::vector<double> far_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalFarNodeIndex);
00112 
00113     CellProperties near_cell_props(r_near_voltages, mTimes);
00114     CellProperties far_cell_props(far_voltages, mTimes);
00115 
00116     //The size of each vector is the number of APs that reached that node
00117     unsigned aps_near_node = near_cell_props.GetMaxUpstrokeVelocities().size();
00118     unsigned aps_far_node = far_cell_props.GetMaxUpstrokeVelocities().size();
00119 
00120     //These should never be empty. If so, an exception should have been thrown in the GetMaxUpstrokeVelocities() method.
00121     assert(aps_near_node > 0);
00122     assert(aps_far_node > 0);
00123 
00124     //if the same number of APs reached both nodes, get the last one...
00125     if (aps_near_node == aps_far_node)
00126     {
00127         t_near = near_cell_props.GetTimeAtLastMaxUpstrokeVelocity();
00128         t_far = far_cell_props.GetTimeAtLastMaxUpstrokeVelocity();
00129     }
00130     //...otherwise get the one with the smallest value, which is the last AP to reach both nodes
00131     //This prevents possible calculation of negative conduction velocities
00132     //for repeated stimuli
00133     else if (aps_near_node > aps_far_node)
00134     {
00135         t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_far_node-1];
00136         t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_far_node-1];
00137     }
00138     else
00139     {
00140         t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_near_node-1];
00141         t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_near_node-1];
00142     }
00143 
00144     if ((globalNearNodeIndex == globalFarNodeIndex) || ( fabs(t_far - t_near) < 1e-8))
00145     {
00146         // globalNearNodeIndex and globalFarNodeIndex are the same node, preventing a 0/0
00147         // or
00148         // AP number i is happening at the same time at nodes globalNearNodeIndex and globalFarNodeIndex
00149         return 0.0;
00150     }
00151     else
00152     {
00153         return euclideanDistance / (t_far - t_near);
00154     }
00155 
00156 
00157 }
00158 
00159 std::vector<double> PropagationPropertiesCalculator::CalculateAllConductionVelocities(unsigned globalNearNodeIndex,
00160                                                                                       unsigned globalFarNodeIndex,
00161                                                                                       const double euclideanDistance)
00162 {
00163     std::vector<double> conduction_velocities;
00164 
00165     std::vector<double> t_near;
00166     std::vector<double> t_far;
00167     unsigned number_of_aps = 0;
00168 
00169     std::vector<double>& r_near_voltages = rCacheVoltages(globalNearNodeIndex);
00170     std::vector<double> far_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalFarNodeIndex);
00171 
00172     CellProperties near_cell_props(r_near_voltages, mTimes);
00173     CellProperties far_cell_props(far_voltages, mTimes);
00174 
00175     t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity();
00176     t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity();
00177 
00178     //exception should have been thrown within the GetTimesAtMaxUpstrokeVelocity method if the threshold is never reached
00179     //and these vectors are empty
00180     assert(t_near.size() !=0);
00181     assert(t_far.size() !=0);
00182 
00183     //Check the node where the least number of aps is reached.
00184     //We will calculate only where AP reached both nodes
00185     if (t_near.size() > t_far.size())
00186     {
00187         number_of_aps = t_far.size();
00188     }
00189     else
00190     {
00191         number_of_aps = t_near.size();
00192     }
00193     //now fill the vector
00194 
00195     if (globalNearNodeIndex == globalFarNodeIndex)
00196     {
00197         // globalNearNodeIndex and globalFarNodeIndex are the same node, preventing a 0/0
00198         for (unsigned i = 0 ; i < number_of_aps;i++)
00199         {
00200             conduction_velocities.push_back(0.0);
00201         }
00202     }
00203     else
00204     {
00205         for (unsigned i = 0 ; i < number_of_aps;i++)
00206         {
00207             if ( fabs(t_far[i] - t_near[i]) < 1e-8)
00208             {
00209                 // AP number i is happening at the same time at nodes globalNearNodeIndex and globalFarNodeIndex
00210                 conduction_velocities.push_back(0.0);
00211             }
00212             else
00213             {
00214                 conduction_velocities.push_back(euclideanDistance / (t_far[i] - t_near[i]));
00215             }
00216         }
00217     }
00218 
00219     return conduction_velocities;
00220 }
00221 
00222 
00223 std::vector<unsigned> PropagationPropertiesCalculator::CalculateAllAboveThresholdDepolarisations(unsigned globalNodeIndex, double threshold)
00224 {
00225     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00226     CellProperties cell_props(r_voltages, mTimes, threshold);
00227     return cell_props.GetNumberOfAboveThresholdDepolarisationsForAllAps();
00228 }
00229 
00230 
00231 unsigned PropagationPropertiesCalculator::CalculateAboveThresholdDepolarisationsForLastAp(unsigned globalNodeIndex, double threshold)
00232 {
00233     std::vector<double>& r_voltages = rCacheVoltages(globalNodeIndex);
00234     CellProperties cell_props(r_voltages, mTimes, threshold);
00235     return cell_props.GetNumberOfAboveThresholdDepolarisationsForLastAp();
00236 }
00237 
00238 
00239 std::vector<double>& PropagationPropertiesCalculator::rCacheVoltages(unsigned globalNodeIndex)
00240 {
00241     if (globalNodeIndex != mCachedNodeGlobalIndex)
00242     {
00243         mCachedVoltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00244         mCachedNodeGlobalIndex = globalNodeIndex;
00245     }
00246     return mCachedVoltages;
00247 }

Generated on Tue May 31 14:31:41 2011 for Chaste by  doxygen 1.5.5