PropagationPropertiesCalculator.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 <sstream>
00033 
00034 PropagationPropertiesCalculator::PropagationPropertiesCalculator(Hdf5DataReader *pDataReader,
00035         const std::string voltageName)
00036         : mpDataReader(pDataReader),
00037         mVoltageName(voltageName)
00038 {}
00039 
00040 PropagationPropertiesCalculator::~PropagationPropertiesCalculator()
00041 {
00042     // We don't own the data reader, so we don't destroy it.
00043 }
00044 
00047 //CellProperties PropagationPropertiesCalculator::GetCellProperties(unsigned globalNodeIndex)
00048 //{
00049 //    std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00050 //    std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00051 //    CellProperties cell_props(voltages, times);
00052 //    return cell_props;
00053 //}
00054 
00055 double PropagationPropertiesCalculator::CalculateMaximumUpstrokeVelocity(unsigned globalNodeIndex)
00056 {
00057     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00058     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00059     CellProperties cell_props(voltages, times);
00060     return cell_props.GetLastMaxUpstrokeVelocity();
00061 }
00062 
00063 std::vector<double> PropagationPropertiesCalculator::CalculateAllMaximumUpstrokeVelocities(unsigned globalNodeIndex, double threshold)
00064 {
00065     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00066     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00067     CellProperties cell_props(voltages, times, threshold);
00068     return cell_props.GetMaxUpstrokeVelocities();
00069 }
00070 
00071 std::vector<double> PropagationPropertiesCalculator::CalculateUpstrokeTimes(unsigned globalNodeIndex, double threshold)
00072 {
00073     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00074     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00075     CellProperties cell_props(voltages, times, threshold);
00076     return cell_props.GetTimesAtMaxUpstrokeVelocity();
00077 }
00078 
00079 double PropagationPropertiesCalculator::CalculateActionPotentialDuration(const double percentage,
00080         unsigned globalNodeIndex)
00081 {
00082     if (percentage < 1.0 || percentage >= 100.0)
00083     {
00084         EXCEPTION("First argument of CalculateActionPotentialDuration() is expected to be a percentage");
00085     }
00086     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00087     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00088     CellProperties cell_props(voltages, times);
00089     return cell_props.GetLastActionPotentialDuration(percentage);
00090 }
00091 
00092 std::vector<double> PropagationPropertiesCalculator::CalculateAllActionPotentialDurations(const double percentage,
00093         unsigned globalNodeIndex, double threshold)
00094 {
00095     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00096     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00097     CellProperties cell_props(voltages, times, threshold);
00098     return cell_props.GetAllActionPotentialDurations(percentage);
00099 }
00100 
00101 double PropagationPropertiesCalculator::CalculatePeakMembranePotential(unsigned globalNodeIndex)
00102 {
00103     std::vector<double> voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNodeIndex);
00104     double max = -DBL_MAX;
00105     for(unsigned i=0; i<voltages.size(); i++)
00106     {
00107         if(voltages[i]>max)
00108         {
00109             max = voltages[i];
00110         }
00111     }
00112     return max;
00113 }
00114 
00115 double PropagationPropertiesCalculator::CalculateConductionVelocity(unsigned globalNearNodeIndex,
00116         unsigned globalFarNodeIndex,
00117         const double euclideanDistance)
00118 {
00119     double t_near = 0;
00120     double t_far = 0;
00121     std::vector<double> near_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNearNodeIndex);
00122     std::vector<double> far_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalFarNodeIndex);
00123     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00124 
00125     CellProperties near_cell_props(near_voltages, times);
00126     CellProperties far_cell_props(far_voltages, times);
00127 
00128     //The size of each vector is the number of APs that reached that node
00129     unsigned aps_near_node = near_cell_props.GetMaxUpstrokeVelocities().size();
00130     unsigned aps_far_node = far_cell_props.GetMaxUpstrokeVelocities().size();
00131 
00132     //If empty, no AP reached the node and no conduction velocity will be calculated
00133     if (aps_near_node == 0 || aps_far_node == 0)
00134     {
00135         EXCEPTION("AP never reached one of the nodes");
00136     }
00137 
00138     //if the same number of APs reached both nodes, get the last one...
00139     if (aps_near_node == aps_far_node)
00140     {
00141         t_near = near_cell_props.GetTimeAtLastMaxUpstrokeVelocity();
00142         t_far = far_cell_props.GetTimeAtLastMaxUpstrokeVelocity();
00143     }
00144     //...otherwise get the one with the smallest value, which is the last AP to reach both nodes
00145     //This prevents possible calculation of negative conduction velocities
00146     //for repeated stimuli
00147     else if (aps_near_node > aps_far_node)
00148     {
00149         t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_far_node-1];
00150         t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_far_node-1];
00151     }
00152     else
00153     {
00154         t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_near_node-1];
00155         t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity()[aps_near_node-1];
00156     }
00157 
00158     if ((globalNearNodeIndex == globalFarNodeIndex) || ( fabs(t_far - t_near) < 1e-8))
00159     {
00160         // globalNearNodeIndex and globalFarNodeIndex are the same node, preventing a 0/0
00161         // or
00162         // AP number i is happening at the same time at nodes globalNearNodeIndex and globalFarNodeIndex        
00163         return 0.0;
00164     }
00165     else
00166     {
00167         return euclideanDistance / (t_far - t_near);
00168     }
00169 
00170     
00171 }
00172 
00173 std::vector<double> PropagationPropertiesCalculator::CalculateAllConductionVelocities(unsigned globalNearNodeIndex,
00174                                                                 unsigned globalFarNodeIndex,
00175                                                                 const double euclideanDistance)
00176 {
00177     std::vector<double> conduction_velocities;
00178 
00179     std::vector<double> t_near;
00180     std::vector<double> t_far;
00181     unsigned number_of_aps = 0;
00182 
00183     std::vector<double> near_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalNearNodeIndex);
00184     std::vector<double> far_voltages = mpDataReader->GetVariableOverTime(mVoltageName, globalFarNodeIndex);
00185     std::vector<double> times = mpDataReader->GetUnlimitedDimensionValues();
00186 
00187     CellProperties near_cell_props(near_voltages, times);
00188     CellProperties far_cell_props(far_voltages, times);
00189 
00190     t_near = near_cell_props.GetTimesAtMaxUpstrokeVelocity();
00191     t_far = far_cell_props.GetTimesAtMaxUpstrokeVelocity();
00192 
00193     //If empty, no AP reached the node and no conduction velocity will be calculated
00194     if (t_near.size() == 0 || t_far.size() == 0)
00195     {
00196         EXCEPTION("AP never reached one of the nodes");
00197     }
00198 
00199     //Check the node where the least number of aps is reached.
00200     //We will calculate only where AP reached both nodes
00201     if (t_near.size() > t_far.size())
00202     {
00203         number_of_aps=t_far.size();
00204     }
00205     else
00206     {
00207        number_of_aps=t_near.size();
00208     }
00209     //now fill the vector
00210     
00211     if (globalNearNodeIndex == globalFarNodeIndex)
00212     {
00213         // globalNearNodeIndex and globalFarNodeIndex are the same node, preventing a 0/0
00214         for (unsigned i = 0 ; i < number_of_aps;i++)
00215         {
00216             conduction_velocities.push_back(0.0);
00217         }        
00218     }
00219     else
00220     {
00221         for (unsigned i = 0 ; i < number_of_aps;i++)
00222         {
00223             if ( fabs(t_far[i] - t_near[i]) < 1e-8)
00224             {
00225                 // AP number i is happening at the same time at nodes globalNearNodeIndex and globalFarNodeIndex
00226                 conduction_velocities.push_back(0.0);
00227             }
00228             else
00229             {
00230                 conduction_velocities.push_back(euclideanDistance / (t_far[i] - t_near[i]));
00231             }
00232         }
00233     }
00234     
00235     return conduction_velocities;
00236 }

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5