Skip to content

Commit c4cbbce

Browse files
committed
latency analysis stats
end of June 2024
1 parent 9301cd4 commit c4cbbce

22 files changed

+1178
-882
lines changed

fitPSTH_pop.m

+546
Large diffs are not rendered by default.

fitPSTH_pop_limpredictor.m

-668
This file was deleted.

getChoiceOutcome.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
successTr = find(dd.successTrials==1);
3939
% wrongSuccTr = find(dd.successTrials==0&~isnan(dd.tOnset)&succDist>=distTh);
4040
% quiescentTr = find(dd.successTrials==0&~isnan(dd.tOnset)&succDist<distTh);
41-
wrongSuccTr = find(dd.successTrials==0&~isnan(dd.tOnset)&~isnan(dd.srt));
41+
wrongSuccTr = find(dd.successTrials==0&~isnan(dd.tOnset)&~isnan(dd.srt)); %ALLWAYS EMPTY
4242
quiescentTr = find(dd.successTrials==0&~isnan(dd.tOnset)&isnan(dd.srt));
4343

4444
choiceOutcome = nan(nTrials,1);

getExampleCells.m

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
%return exemplery cells 2024 March
2+
3+
[saveServer, rootFolder] = getReady();
4+
load(fullfile(saveServer,'param20240625.mat'),'param');
5+
6+
animal = 'hugo';%'ollie';%'andy';% 'andy' '
7+
tgtModality = 'all';%'eyeSpeed';
8+
9+
dataDir = '/mnt/syncitium/Daisuke/cuesaccade_data OBS/figPSTH_pop20231026hugo/';
10+
11+
12+
%% load gain info <> avg tgt resp [HACK]
13+
%from fitPSTH_pop_limpredictor.m (?)
14+
load(fullfile(dataDir,'fitPSTH_pop20231026hugo.mat'),...
15+
'id_pop','kernel_pop','tlags');
16+
17+
%preferred direction & amplitude of each kernel modality
18+
tgtRange = [0.05 0.15; 0.03 0.25; -0.1 0.1];
19+
prefDirOption = 0;
20+
[kernelPrefDir, kernelAmp] = getKernelPrefDirAmp(kernel_pop, tlags, tgtRange, param.cardinalDir, prefDirOption);
21+
22+
23+
%% load kernel info from tgt units
24+
% not used any more??
25+
% gainKernelName = fullfile(dataDir,'gainkernel_splt_all.mat');
26+
% if exist(gainKernelName, 'file')
27+
% load(gainKernelName);
28+
% end
29+
30+
%% exclude NG units
31+
%from pickUnitsByClass
32+
load(fullfile(dataDir,'pickUnitsByClass.mat'),"funcClass",'nUnits');
33+
34+
%% tgt units
35+
highAmp = true;
36+
if highAmp
37+
suffix = '_highAmp';
38+
param.ampTh = .5;
39+
else
40+
suffix = '';
41+
end
42+
for itgtModality = 1:3
43+
switch itgtModality
44+
case 1
45+
tgtModality = 'vision';
46+
case 2
47+
tgtModality = 'eyeSpeed';
48+
case 3
49+
tgtModality = 'eyePosition';
50+
end
51+
for iprefDir =1%:8
52+
53+
prefDir_q = quantizeDir(kernelPrefDir(:,itgtModality), param.cardinalDir);
54+
if ~highAmp
55+
tgtID = id_pop(prefDir_q== param.cardinalDir(iprefDir));
56+
else
57+
tgtID = id_pop(prefDir_q== param.cardinalDir(iprefDir) & ...
58+
kernelAmp(:,itgtModality) > param.ampTh);
59+
end
60+
61+
tgtID = intersect(funcClass.id_all, tgtID);%exclude NG units
62+
63+
[~,tgtIDidx] = intersect(id_all, tgtID);
64+
65+
66+
id_tgtModality{itgtModality, iprefDir} = id_pop(tgtIDidx);
67+
68+
69+
end
70+
end
71+
72+
save(fullfile(dataDir,'exampleCells.mat'), 'id_tgtModality');

getPrefDir.m

+3-41
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
% created from showTonsetResp.m
66

77
[avgOnsetResp, winSamps, singleOnsetResp, ...
8-
sortedOnsetLabels, uniqueOnsetLabels] ...
8+
tgtDir_valid, uniqueOnsetLabels] ...
99
= eventLockedAvg(y_r', t_r, onsetTimes, tgtDir, param.figTWin);
1010

1111
tonsetRespAmp = characteriseResp(singleOnsetResp, ...
@@ -15,47 +15,9 @@
1515

1616
%prefDir = 180/pi*circ_mean(tgtDir'/180*pi,tonsetRespAmp_p(:,psthIdx)); %NG
1717
%psthIdx = find(strcmp(psthNames, 'psth'));
18-
[fitPars, fitErr, r] = fitResponse(tgtDir, tonsetRespAmp, param.cardinalDir);
18+
[fitPars, fitErr, r] = fitResponse(tgtDir_valid, tonsetRespAmp, param.cardinalDir);
1919
prefDir = fitPars(1); %[deg]
2020
[~, prefDirIdx] = min(abs(circ_dist(pi/180*param.cardinalDir, pi/180*prefDir)));
2121
prefDir_quantized = param.cardinalDir(prefDirIdx);
22-
prefDirTrials = find(tgtDir == prefDir_quantized);%trials with cell's preferred direction
22+
prefDirTrials = find(tgtDir_valid == prefDir_quantized);%trials with cell's preferred direction
2323

24-
25-
26-
% % created from dirTuinig_pupil.m
27-
% % UNDER CONSTRUCTION
28-
%
29-
% %% direction tuning
30-
% dirs = unique(dd.targetloc);
31-
% mresp = zeros(length(dirs),3);
32-
% mparea = [];
33-
% for idir = 1:length(dirs)
34-
%
35-
%
36-
% theseTr = intersect(find(dd.successTrials), find(dd.targetloc==dirs(idir)));
37-
%
38-
% resp_c = [];
39-
% parea_c = [];
40-
% for itr = 1:length(theseTr)
41-
% thisTr = theseTr(itr);
42-
% theseTimes = intersect(find(eyeData(thisTr).t - dd.tOnset(thisTr) > 1e-3*respWin(1)), ...
43-
% find(eyeData(thisTr).t - dd.tOnset(thisTr) < 1e-3*respWin(2)));
44-
% resp_c(itr) = sum(psth_tr{thisTr}(theseTimes))/diff(respWin)/1e-3; %[spikes/s]
45-
%
46-
% theseTimes_pre = intersect(find(eyeData(thisTr).t - dd.tOnset(thisTr) > 1e-3*preWin(1)), ...
47-
% find(eyeData(thisTr).t - dd.tOnset(thisTr) < 1e-3*preWin(2)));
48-
%
49-
% parea_c(itr) = mean(eyeData_rmblk_tr(thisTr).parea(theseTimes_pre));
50-
% end
51-
% mresp(idir,1) = mean(resp_c);
52-
% mresp(idir,2) = nanmean(resp_c(parea_c<parea_avg));
53-
% mresp(idir,3) = nanmean(resp_c(parea_c>parea_avg));
54-
% mparea(idir) = mean(parea_c);
55-
% length(find(parea_c>parea_avg))
56-
% end
57-
%
58-
% plot(dirs, mresp);
59-
% legend('all trials','parea<mean','parea>mean');
60-
% xlabel('tgt direction [deg]');
61-
% %polarplot(dirs/180*pi, mresp);

getPrevDir.m

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function [prevDir_quantized, prevDirTrials] = getPrevDir(tgtDir, param)
2+
%[prevDir_quantized, prevDirTrials] = getPrevDir(tgtDir, param)
3+
% return the most prevalent stimulus direction
4+
% Note this direction is irrelevant of neural response
5+
% see also: getPrefDir
6+
7+
prevDir = mode(tgtDir);
8+
[~, prevDirIdx] = min(abs(circ_dist(pi/180*param.cardinalDir, pi/180*prevDir)));
9+
prevDir_quantized = param.cardinalDir(prevDirIdx);
10+
prevDirTrials = find(tgtDir == prevDir_quantized);%trials with cell's preferred direction

getReady.m

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
%addpath(genpath('/home/daisuke/Documents/git'));
1515
rmpath(genpath('/home/daisuke/Documents/git/VariabilityEarlyVisualCortex/matlab/'))
1616
rmpath(genpath('/home/daisuke/Documents/git/dsbox/chronux_2_11/'));
17+
rmpath(genpath('/home/daisuke/Documents/git/chronux_2_11'));
1718
%saveServer = '~/Documents/cuesaccade_data';
1819
%saveServer = '/mnt/syncitium/Daisuke/cuesaccade_data';
1920
saveServer = '/media/daisuke/cuesaccade_data';

getRewardTimes.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
function [trialEndTimes, successTimes, trialOutcome] = getRewardTimes(dd)
2-
%[rewardTimes, unishTimes, successTimes, trialOutcome] = getRewardTimes(dd)
2+
%[trialEndTimes, successTimes, trialOutcome] = getRewardTimes(dd)
33
%returns times of reward delivery detected as item2delivered
44
%
55
%cf. concatenate_eye.m

getSingleTrialLatency.m

+32-11
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1-
function [latency_neuro, thresh_neuro] = getSingleTrialLatency(singleResp_t, winSamps_t, tWin_t, threshOption, Thresh)
1+
function [latency_neuro, thresh_neuro] = getSingleTrialLatency(singleResp_t, winSamps_t, ...
2+
tWin_t, threshParam)
23
%[latency_neuro, thresh_neuro] = getSingleTrialLatency(singleResp_t, winSamps_t, tWin_t, threshOption)
34
% from latencyV1MT/secondary/findSingleTrialLatency.m
45
% singleResp_t: trial x time
56

67
baseline = 'tonset'; %used to have an option of fonset but turned out to be noisier
78

8-
if nargin < 5
9-
Thresh = 4; %s.d.
10-
end
119
if nargin < 4
12-
threshOption = 'individual'; %india's choice
10+
threshParam.dur = 0;
11+
threshParam.thresh = 4; %s.d.
12+
threshParam.option = 'individual'; %india's choice
1313
end
1414

15+
assert(strcmp(threshParam.option, 'individual') + strcmp(threshParam.option, 'uniform') )
16+
1517
latencyLimit = [0 tWin_t(2)];
1618
x = 1e-2*round(1e2*winSamps_t);
1719
sdf_t = singleResp_t; %trial x time
1820

21+
dt = median(diff(x));
22+
tidx_dur = round(threshParam.dur/dt)-1;
23+
1924
%% define threshold
2025
thresh_neuro = nan(size(sdf_t,1),1);
21-
if strcmp(threshOption, 'individual')
26+
if strcmp(threshParam.option, 'individual')
2227
for itr = 1:size(sdf_t,1)
2328

2429
if strcmp(baseline, 'tonset')
@@ -27,17 +32,17 @@
2732

2833
sd = std(sdf_pre(:));
2934
mu = mean(sdf_pre(:));
30-
thresh = mu + Thresh*sd; %compute each trail or across all trials?
35+
thresh = mu + threshParam.thresh*sd; %compute each trail or across all trials?
3136
thresh_neuro(itr) = thresh;
3237
end
33-
elseif strcmp(threshOption, 'uniform');
38+
elseif strcmp(threshParam.option, 'uniform');
3439
if strcmp(baseline, 'tonset')
3540
sdf_pre = sdf_t(:,x<0);
3641
end
3742

3843
sd = std(sdf_pre(:));
3944
mu = mean(sdf_pre(:));
40-
thresh = mu + Thresh*sd; %compute each trail or across all trials?
45+
thresh = mu + threshParam.thresh*sd; %compute each trail or across all trials?
4146
thresh_neuro(:) = thresh;
4247
end
4348

@@ -46,8 +51,23 @@
4651
latency_neuro = nan(size(sdf_t,1),1);
4752
for itr = 1:size(sdf_t,1)
4853
j = find(x >= 0,1);
49-
if j ~= size(sdf_t,2)
50-
latency = x(find(sdf_t(itr,j:end) >= thresh_neuro(itr),1) + j-1); %Calculates latency as first time point after stimulus where sdf is >= threshold
54+
tidx_a = find(sdf_t(itr,j:end) >= thresh_neuro(itr)) + j-1;
55+
56+
if j ~= size(sdf_t,2) && ~isempty(tidx_a)
57+
%Calculates latency as first time point after stimulus where sdf is >= threshold
58+
59+
for xxx = 1:numel(tidx_a)
60+
tidx = tidx_a(xxx);
61+
62+
%minimal duration surpassing the threshold
63+
if isempty(find(tidx+tidx_dur<=numel(x), 1))
64+
latency = NaN; continue;
65+
elseif sum(sdf_t(itr, tidx:tidx+tidx_dur) >= thresh_neuro(itr)) == tidx_dur+1
66+
latency = x(tidx); break;
67+
else
68+
latency = NaN;
69+
end
70+
end
5171
else
5272
latency = NaN;
5373
end
@@ -60,6 +80,7 @@
6080
if isempty(latency)
6181
latency = NaN;
6282
end
83+
6384

6485
latency_neuro(itr) = latency;
6586
end

getTgtLatencyCorr.m

+56-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
function [latency_neuro, latency_bhv, latcorr, f, fneuro] = getTgtLatencyCorr(PSTH_f, t_r, onsets_cat, ...
2-
catEvTimes, tWin_t, Thresh, param, dd )
2+
catEvTimes, tWin_t, param, dd, validEvents )
33
% [latency_neuro, latency_bhv, r, f, fneuro] = getTgtLatencyCorr(PSTH_f, t_r, onsets_cat, ...
44
% catEvTimes, tWin_t, Thresh, param, dd)
55
% computes neural and behavioural latencies with or without cue
66

7-
%validEvents = intersect(find(~isnan(onset)), find(dd.cueOn==icue-1));
8-
%< this condition only includes all trials irrespective of the trial outcome
9-
validEvents = find(~isnan(catEvTimes.tOnset) .* ~isnan(catEvTimes.fOnset)); %with or without cue
7+
corrOption = 'Spearman'; %'Pearson'
108

119
%% neural latency
1210
[latency_neuro, ~,~,fneuro] = getTgtNeuroLatency(PSTH_f, t_r, onsets_cat, ...
13-
catEvTimes, tWin_t, Thresh, param, dd, validEvents);
11+
catEvTimes, tWin_t, param.threshParam, param, dd, validEvents);
1412

1513
%% behavioural latency
1614
option = 1;
@@ -26,37 +24,80 @@
2624
fail = choiceOutcome(validEvents) >= 2;
2725

2826

29-
%% select trials with preferred direction (showTonsetResp)
3027
theseEvents = validEvents;%(success);%better to use all conditions??
3128
onsetTimes = catEvTimes.tOnset;
3229
onsetTimes = onsetTimes(theseEvents);
3330
tgtDir = getTgtDir(dd.targetloc, param.cardinalDir);
3431
tgtDir = tgtDir(theseEvents);
32+
33+
%% select trials with preferred direction (showTonsetResp)
3534
[prefDir, prefDirTrials] = getPrefDir(PSTH_f, t_r, onsetTimes, tgtDir, param);
36-
tgt_in = zeros(numel(validEvents),1);
37-
tgt_in(prefDirTrials) = 1;
35+
tgt_pref = zeros(numel(validEvents),1);
36+
tgt_pref(prefDirTrials) = 1;
3837

38+
%% select trials with most frequent direction
39+
[prevDir, prevDirTrials] = getPrevDir(tgtDir, param);
40+
tgt_prev = zeros(numel(validEvents),1);
41+
tgt_prev(prevDirTrials) = 1;
3942

4043
validLatency = ~isnan(latency_neuro);
4144

4245
%correlation beteween behaviour and neuro using only successful trials
43-
latcorr.r = corr(latency_bhv(logical(validLatency.*~isnan(latency_bhv))), latency_neuro(logical(validLatency.*~isnan(latency_bhv))));
44-
latcorr.r_success = corr(latency_bhv(logical(success.*validLatency)), latency_neuro(logical(success.*validLatency)));
45-
latcorr.r_pref = corr(latency_bhv(logical(validLatency.*~isnan(latency_bhv).*tgt_in)), latency_neuro(logical(validLatency.*~isnan(latency_bhv).*tgt_in)));
46-
latcorr.r_success_pref = corr(latency_bhv(logical(success.*validLatency.*tgt_in)), latency_neuro(logical(success.*validLatency.*tgt_in)));
46+
try
47+
[latcorr.r, latcorr.p] = corr(latency_bhv(logical(validLatency.*~isnan(latency_bhv))), ...
48+
latency_neuro(logical(validLatency.*~isnan(latency_bhv))), 'type', corrOption);
49+
catch err
50+
latcorr.r = nan;
51+
latcorr.p = nan;
52+
end
53+
try
54+
[latcorr.r_success, latcorr.p_success] = corr(latency_bhv(logical(success.*validLatency)), ...
55+
latency_neuro(logical(success.*validLatency)), 'type', corrOption);
56+
catch err
57+
latcorr.r_success = nan;
58+
latcorr.p_success = nan;
59+
end
60+
try
61+
[latcorr.r_pref, latcorr.p_pref] = corr(latency_bhv(logical(validLatency.*~isnan(latency_bhv).*tgt_pref)), ...
62+
latency_neuro(logical(validLatency.*~isnan(latency_bhv).*tgt_pref)), 'type', corrOption);
63+
catch err
64+
latcorr.r_pref = nan;
65+
latcorr.p_pref = nan;
66+
end
67+
try
68+
[latcorr.r_success_pref, latcorr.p_success_pref] = corr(latency_bhv(logical(success.*validLatency.*tgt_pref)), ...
69+
latency_neuro(logical(success.*validLatency.*tgt_pref)), 'type', corrOption);
70+
catch err
71+
latcorr.r_success_pref = nan;
72+
latcorr.p_success_pref = nan;
73+
end
74+
try
75+
[latcorr.r_success_prev, latcorr.p_success_prev] = corr(latency_bhv(logical(success.*validLatency.*tgt_prev)), ...
76+
latency_neuro(logical(success.*validLatency.*tgt_prev)), 'type', corrOption);
77+
catch err
78+
latcorr.r_success_prev = nan;
79+
latcorr.p_success_prev = nan;
80+
end
4781

4882
if nargout > 3
4983
f = figure;
5084
plot(latency_bhv(logical(wCue.*success)), latency_neuro(logical(wCue.*success)),'ro','DisplayName','success w cue'); hold on;
5185
plot(latency_bhv(logical(woCue.*success)), latency_neuro(logical(woCue.*success)),'bo','DisplayName','succes wo cue'); hold on;
52-
plot(latency_bhv(logical(wCue.*success.*tgt_in)), latency_neuro(logical(wCue.*success.*tgt_in)),'o','MarkerFaceColor','r','DisplayName','success w cue prefDir'); hold on;
53-
plot(latency_bhv(logical(woCue.*success.*tgt_in)), latency_neuro(logical(woCue.*success.*tgt_in)),'o','MarkerFaceColor','b','DisplayName','succes wo cue prefDir'); hold on;
86+
plot(latency_bhv(logical(wCue.*success.*tgt_pref)), latency_neuro(logical(wCue.*success.*tgt_pref)),'o','MarkerFaceColor','r','DisplayName','success w cue prefDir'); hold on;
87+
plot(latency_bhv(logical(woCue.*success.*tgt_pref)), latency_neuro(logical(woCue.*success.*tgt_pref)),'o','MarkerFaceColor','b','DisplayName','succes wo cue prefDir'); hold on;
5488
plot(latency_bhv(logical(wCue.*fail)), latency_neuro(logical(wCue.*fail)),'rx','DisplayName','failure w cue'); hold on;
5589
plot(latency_bhv(logical(woCue.*fail)), latency_neuro(logical(woCue.*fail)),'bx','DisplayName','failure wo cue'); hold on;
5690
xlabel('behavioural latency');
5791
ylabel('neural latency');
5892
legend('location','eastoutside');
59-
tname = sprintf('all dir: %.2f, success all dir: %.2f \n success pref dir: %.2f', latcorr.r, latcorr.r_success, latcorr.r_success_pref);
93+
tname = sprintf(['all dir: %.2f (p=%.2f), \n' ...
94+
'success all dir: %.2f (p=%.2f) \n' ...
95+
'success pref dir: %.2f (p=%.2f)\n' ...
96+
'success prev dir: %.2f (p=%.2f)'], ...
97+
latcorr.r, latcorr.p, ...
98+
latcorr.r_success, latcorr.p_success, ...
99+
latcorr.r_success_pref, latcorr.p_success_pref,...
100+
latcorr.r_success_prev, latcorr.p_success_prev);
60101
title(tname); %title(['r=' num2str(r) ', r(success)=' num2str(r_success)]);
61102
squareplot;
62103
axis padded; set(gca,'TickDir','out');

0 commit comments

Comments
 (0)