How do I extract the firing threshold value from an action potential phase plot?

24 visualizaciones (últimos 30 días)
Hi,
I am managing to produce a phase plot and I can zoom into it to see a closely approximated value for the firing threshold (first kink with a blue arrow pointing to in the attached figure). How do I extract this value without using ginput?
My code to produce the figure and extract the value using ginput:
% Roksana's script to plot .smr average AP phase plot
% 20210127
% For troubleshooting analysis - cleans the workspace
clear
close all
%Import data
load('C:\xyz.mat')
%Define channel to plot
data = xyz;
vm = data.values;
%scale x-axis by interval
t = linspace(0,length(vm)*data.interval,length(vm));
%derive membrane potential
dA = diff(data.values);
%omit last value so vectors are of equal length
data.values(end)=[];
%plot derivative dV/dt over Vm
figure;
plot(data.values,dA);
xlabel('Membrane Potential (Vm)');
ylabel('dV/dt');
title('Phase Plot');
%find firing threshold
zoom on;
pause()
zoom off;
[x, ~] = ginput
zoom out;
  2 comentarios
Roksana Khalid
Roksana Khalid el 2 de Feb. de 2021
Yes, same topic and data.
The membrane potential value (x-axis) I get from here corresponds to the y-values I want to set on the plot in the other question.

Iniciar sesión para comentar.

Respuesta aceptada

Mathieu NOE
Mathieu NOE el 2 de Feb. de 2021
hello again....
so my second submission for you today !
attached also 2 subfunction for crossing points computation and a better derivative method
i used a bit of smoothing befor the derivation to improve the quality of the data , especially in the "corners".
it's more or less a second alternative to the technique employed in the other post (BTW you could here also compute width and area if needed)
%Import data
load('xyz.mat')
%Define channel to plot
% data = xyz;
% vm = data.values;
% S2C1_17082020_WM_apomorphine_20uM_Ch1 =
%
% struct with fields:
%
% title: 'voltage'
% comment: 'No comment'
% interval: 4.0000e-05
% scale: 0.0153
% offset: 0
% units: 'mV'
% start: 0
% length: 1122
% values: [1122×1 double]
vm = S2C1_17082020_WM_apomorphine_20uM_Ch1.values;
samples = length(vm);
dt = S2C1_17082020_WM_apomorphine_20uM_Ch1.interval;
t_final = samples*dt;
%scale x-axis by interval
t = linspace(0, t_final,samples);
% smoothin a bit the data
vm_smoo = sgolayfilt(vm,1,15);
figure(1);
plot(t,vm,'b',t,vm_smoo,'r');
ylabel('V (mV)');
xlabel('Time (s)');
legend('raw','sgolay filtered');
title('Membrane potential')
% compute first derivative on raw and smoothed data
[dvm, ddvm] = firstsecondderivatives(t,vm);
[dvm_smoo, ddvm_smoo] = firstsecondderivatives(t,vm_smoo);
% 1st knee point has slope approx 1/1.5 of max slope (positive threshold, positive slope)
% 2nd knee point has slope approx 1/10th of max slope (negative threshold, positive slope)
a_pos1 = 1.5;
pos_slope_max = max(dvm_smoo(dvm_smoo>0));
pos_slope_trigger = pos_slope_max/a_pos1;
a_pos2 = 10;
neg_slope_max = min(dvm_smoo(dvm_smoo<0));
neg_slope_trigger = neg_slope_max/a_pos2;
% use crossing_V7 function to find and interpolate crossing points
[ind_pos1,t0_pos1,s0_pos1,~,~,~] = crossing_V7(dvm_smoo,t,pos_slope_trigger,'linear');
[ind_pos2,t0_pos2,s0_pos2,~,~,~] = crossing_V7(dvm_smoo,t,neg_slope_trigger,'linear');
% select first one (can be multiple if measurement noise - shoudn't be especially after filtering)
t0_pos1 = t0_pos1(1);
t0_pos2 = t0_pos2(1);
vm_knee1 = interp1(t,vm,t0_pos1,'linear');
vm_knee2 = interp1(t,vm,t0_pos2,'linear');
dvm_knee1 = interp1(t,dvm,t0_pos1,'linear');
dvm_knee2 = interp1(t,dvm,t0_pos2,'linear');
figure(2);
plot(t,vm,'b',t0_pos1,vm_knee1,'+r',t0_pos2,vm_knee2,'+g')
ylabel('V (mV)')
xlabel('Time (s)')
title('Membrane potential')
figure(3);
plot(vm,dvm,'b',vm_knee1,dvm_knee1,'+r',vm_knee2,dvm_knee2,'+g')
xlabel('Voltage (mV)')
ylabel('dV/dt (mV/s)')
title('Membrane potential')
  3 comentarios
Mathieu NOE
Mathieu NOE el 3 de Feb. de 2021
hello again
see first my answer in the other post
fine tunong my slope threshold to 7e3 mV/s led to find the exact point your showing
hope this helps
%Import data
load('xyz.mat')
% load('AP2.mat')
vm = S2C1_17082020_WM_apomorphine_20uM_Ch1.values;
samples = length(vm);
dt = S2C1_17082020_WM_apomorphine_20uM_Ch1.interval;
t_final = samples*dt;
%scale x-axis by interval
t = linspace(0, t_final,samples);
% compute first derivative on data
[dvm, ddvm] = firstsecondderivatives(t,vm);
figure(1);
subplot(2,1,1),plot(t,vm,'b');
ylabel('V (mV)');
subplot(2,1,2),plot(t,dvm,'b');
ylabel('dV/dt (mV/s)');
xlabel('Time (s)');
title('Membrane potential')
% 1st knee point has slope approx 1/N th of max slope (positive threshold, positive slope)
% 2nd knee point has slope approx 1/N th of max slope (negative threshold, positive slope)
% a_pos1 = 150;
% pos_slope_max = max(dvm(dvm>=0));
% pos_slope_trigger = pos_slope_max/a_pos1; % 4e3
pos_slope_trigger = 7e3;
% a_pos2 = 25;
% neg_slope_max = min(dvm(dvm<=0));
% neg_slope_trigger = neg_slope_max/a_pos2; % -4e3
neg_slope_trigger = -7e3;
indpos = find(dvm>=pos_slope_trigger)
t0_pos1 = t(indpos(1));
indneg = find(dvm<=neg_slope_trigger)
t0_pos2 = t(indneg(end));
vm_knee1 = interp1(t,vm,t0_pos1,'linear');
vm_knee2 = interp1(t,vm,t0_pos2,'linear');
dvm_knee1 = interp1(t,dvm,t0_pos1,'linear');
dvm_knee2 = interp1(t,dvm,t0_pos2,'linear');
figure(2);
plot(t,vm,'b',t0_pos1,vm_knee1,'+r',t0_pos2,vm_knee2,'+g')
ylabel('V (mV)')
xlabel('Time (s)')
title('Membrane potential')
figure(3);
plot(vm,dvm,'b',vm_knee1,dvm_knee1,'+r',vm_knee2,dvm_knee2,'+g')
xlabel('Voltage (mV)')
ylabel('dV/dt (mV/s)')
title('Membrane potential')

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Visual Exploration en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by