function [init_idx, a_plot] = calcInitVmV3hKpTinterp(s, max_idx, min_idx, ...
lo_thr, hi_thr, plotit)
% calcInitVmV3hKpTinterp - Calculates candidates for action potential threshold using the first three time-domain derivatives.
%
% Usage:
% [init_idx, a_plot] =
% calcInitVmV3hKpTinterp(s, max_idx, min_idx, lo_thr, hi_thr, plotit)
%
% Description:
% First uses interpolation to increase time points. Calculates h,
% the second derivative of phase-plane (d^2 v'/dv^2), in terms of
% time-domain derivatives. Also calculates Kp = V''[1 + (V')^2]^(-3/2),
% the curvature. The maxima of these functions are used as candidates
% for AP thresholds.
%
% Parameters:
% s: A spike_shape object.
% max_idx: The index of the maximal point of the spike_shape [dt].
% min_idx: The index of the minimal point of the spike_shape [dt].
% lo_thr, hi_thr: Lower and higher thresholds for time derivative of voltage.
% plotit: If non-zero, plot a graph annotating the test results
% (optional).
%
% Returns:
% init_idx: Indices of threshold candidates in the spike_shape [dt].
% a_plot: plot_abstract, if requested.
%
% See also: calcInitVm
%
% $Id$
%
% Author:
% Cengiz Gunay <cgunay@emory.edu>, 2004/11/18
% Taken from Sekerli, Del Negro, Lee and Butera. IEEE Trans. Biomed. Eng.,
% 51(9): 1665-71, 2004.
% Copyright (c) 2007 Cengiz Gunay <cengique@users.sf.net>.
% This work is licensed under the Academic Free License ("AFL")
% v. 3.0. To view a copy of this license, please look at the COPYING
% file distributed with this software or visit
% http://opensource.org/licenses/afl-3.0.php.
if ~ exist('plotit', 'var')
plotit = 0;
end
a_plot = [];
% Supersampling factor (times as many new data points)
int_fac = 4;
%num_points = 200;
%interp_v = interp(s.trace.data(1 : max_idx), int_fac)';
interp_v = pchip(1 : max_idx, s.trace.data(1 : max_idx), ...
(1 : (max_idx * int_fac))/int_fac)';
dt = s.trace.dt / int_fac;
size(interp_v)
d3 = diff3T_h4(interp_v * s.trace.dy, dt);
d2 = diff2T_h4(interp_v * s.trace.dy, dt);
d1 = diffT(interp_v * s.trace.dy, dt);
% Remove boundary artifacts
d3 = d3(3:(end - 2));
d2 = d2(3:(end - 2));
d1 = d1(3:(end - 2));
% Find desired lower boundary of region of interest
low_d1_idx = find(d1 > lo_thr);
if length(low_d1_idx) == 0
error('calcInitVm:failed', ...
['Failed to find any points below low derivative threshold ' ...
num2str(lo_thr) ]);
end
low_d1_idx = low_d1_idx(1);
hi_d1_idx = find(d1 < hi_thr);
if length(hi_d1_idx) == 0
error('calcInitVm:failed', ...
['Failed to find any points above high derivative threshold ' ...
num2str(hi_thr) ]);
end
hi_d1_idx = hi_d1_idx(end);
[max_d1, max_d1_idx] = max(d1);
% Sekerli's method, max of second derivative
h = (d3 .* d1 - d2 .* d2) ./ (d1 .* d1 .* d1);
s_props = get(s, 'props');
% OBSOLETE, SEE BELOW.
% If specified, use threshold as upper limit
if isfield(s_props, 'init_threshold')
add_h_title = [', while v\prime < ' num2str(s_props.init_threshold)];
constrained_idx = find(d1 < s_props.init_threshold);
if length(constrained_idx) == 0
error('calcInitVm:failed', ...
['Failed to find any points below derivative threshold ' ...
num2str(s_props.init_threshold) ]);
else
[val, max_h_idx] = max(h(constrained_idx));
max_h_idx = constrained_idx(max_h_idx);
end
else
add_h_title = '';
[val, max_h_idx] = max(h);
end
max_h_idx = (max_h_idx + 2) / int_fac;
% Curvature
k1 = 1 + d1 .* d1;
k = d2 ./ sqrt(k1 .* k1 .* k1);
% Find maximum of k between given derivative thresholds and on the rising edge
constrained_idx = find(d1 >= lo_thr & d1 <= hi_thr & d2 > 0);
if length(constrained_idx) == 0
warning('calcInitVm:failed', ...
['Failed to find any points between derivative thresholds (' ...
num2str(lo_thr), ' - ', num2str(hi_thr) ') while v'''' > 0. ' ...
'Using supersampled slope threshold crossing method (7) instead.']);
max_k_idx = NaN;
max_h_idx = NaN;
[max_slope_idx a_plot] = ...
calcInitVmSlopeThresholdSupsample(s, max_idx, min_idx, ...
s_props.init_threshold, plotit);
else
[val, max_k_idx] = max(k(constrained_idx));
max_k_idx = (constrained_idx(max_k_idx) + 2) / int_fac;
[val, max_h_idx] = max(h(constrained_idx));
max_h_idx = constrained_idx(max_h_idx);
max_h_idx = (max_h_idx + 2) / int_fac;
end
if plotit
t = (3 : (int_fac * max_idx - 2)) * dt * 1e3;
if isfield(s_props, 'quiet') || isfield(s.trace.props, 'quiet')
title_str = '';
else
title_str = [ strrep(class(s), '_', ' ') ': ' get(s, 'id') ', ' ];
end
a_plot = ...
plot_abstract({(1:max_idx) * s.trace.dt * 1e3, ...
s.trace.data(1:max_idx)/max(abs(s.trace.data(1:max_idx))), ...
(1:(max_idx * int_fac)) * dt * 1e3, ...
interp_v/max(abs(interp_v)), ...
t, d1/max(abs(d1)), t, d2/max(abs(d2)), ...
t, d3/max(abs(d3)), t, h/max(abs(h)), '.-', ...
t, k/max(abs(k)), '.-', ...
max_h_idx * s.trace.dt * 1e3, ...
interp_v(max_h_idx * int_fac)/max(abs(interp_v)), 's', ...
max_k_idx * s.trace.dt * 1e3, ...
interp_v(max_k_idx * int_fac)/max(abs(interp_v)), 'vk', ...
}, ...
{'time [ms]', 'normalized'}, ...
[ title_str 'time-plane methods, ' ...
'max of h = d^2v\prime/dv^2' add_h_title ...
' and curvature K_p = v\prime\prime[1 + v\prime^2]^{-3/2}, ' ...
'while ' num2str(lo_thr) ' < v\prime < ' num2str(hi_thr)], ...
{['v / ' sprintf('%.2e', max(abs(s.trace.data(1:max_idx))))], ...
['v / ' sprintf('%.2e', max(abs(interp_v))) ' (interp)'], ...
['v\prime / ' sprintf('%.2e', max(abs(d1))) ], ...
['v\prime\prime / ' sprintf('%.2e', max(abs(d2))) ], ...
['v\prime\prime\prime / ' sprintf('%.2e', max(abs(d3))) ], ...
['h / ' sprintf('%.2e', max(abs(h))) ], ...
['K_p / ' sprintf('%.2e', max(abs(k))) ], ...
'max h(t)', 'max K_p(t)'}, 'plot');
% sprintf('\n') ...
a_plot = setProp(a_plot, 'axisLimits', ...
[(low_d1_idx * dt * 1e3) (max_idx * s.trace.dt * 1e3) NaN NaN]);
end
init_idx = [ max_h_idx max_k_idx ];