forked from carlosloza/MPP-EEG
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Embedding_Trans.m
169 lines (148 loc) · 4.76 KB
/
Embedding_Trans.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
% Function that performs the Embedding Transform on a set of single-channel
% bandpassed EEG recordings
% Author: Carlos Loza
%%
function [X_M_snippet_tr, beta_tr, beta_all] = Embedding_Trans(X,M)
% INPUTS:
% X - EEG data. It can be 1. single-trial (row vector)
% 2. multi-trial/same duration (matrix form), or
% 3. multi-trial/different durations (cell) input of single-channel
% bandpassed EEG data
% KEY: Single traces MUST be row vectors
% M - Dimensionality of embedding, i.e. duration (in samples) of putative
% events
% OUTPUTS:
% X_M_snippet_tr - M-snippets separated by trials
% beta_tr - Amplitude/Norm of all possible M-dimensional snippets separated
% by trials and mapped directly to the M-snippets in X_M_snippet_tr
% beta_all - Amplitude/Norm of all possible M-dimensional snippets for all
% trials, i.e. Embedding Transform
% Check if input is cell
X = squeeze(X);
n_tr = size(X,1);
if iscell(X) == 0
X = mat2cell(X,ones(1,n_tr));
end
X_M_snippet_tr = cell(n_tr,1);
beta_tr = cell(n_tr,1);
% Amplitude of Hilbert Transform
X_abs = cell(n_tr,1);
for i = 1:n_tr
X_abs{i,1} = abs(hilbert(X{i,1}));
end
% Smooth the instantaneous amplitudes
X_abs_sm = cell(n_tr,1);
aux_M = round(M/2);
spn = round(aux_M/2)*2 - 1;
for i = 1:n_tr
X_abs_sm{i,1} = smooth(X_abs{i,1},spn);
end
% Find peaks first (Putative neuromodulations)
X_pks = cell(n_tr,1);
min_pk_d = round(1*M); % Minimum distance between adjacent peaks
for i = 1:n_tr
[~, pk_loc] = findpeaks(X_abs_sm{i,1},'MinPeakDistance',min_pk_d,'SortStr','descend');
X_pks{i,1} = pk_loc;
end
% Embedding Transform
beta_all = zeros(0,0);
for i = 1:n_tr
[X_M_snippet, beta_aux] = Embedding_Trans_all(X{i,1},M,X_pks{i,1});
beta_all = [beta_all; abs(beta_aux)]; % Stack norms from all trials
X_M_snippet_tr{i,1} = X_M_snippet;
beta_tr{i,1} = beta_aux;
end
end
%%
function [X_M_snippet, beta_trial] = Embedding_Trans_all(x,M,pk_loc)
% INPUTS:
% x - Single-channel, single-trial bandpassed EEG trace
% M - Dimensionality of embedding, i.e. duration (in samples) of putative
% events
% pk_loc - Timestamps of peaks in the instantaneous amplitude trace
% corresponding to input x
% OUTPUTS:
% X_M_snippet -
% beta_trial - Amplitude/Norm of all possible M-dimensional snippets, i.e.
% Embedding Transform
% X_M_snippet - M-snippets discovered/extracted in the current trial
N = length(x);
L = ceil((N+M-1)/M); % Maximum possible number of non-overlapping atoms
stp_fl = 0; % Stopping criterion/flag
X_M_snippet = zeros(M,L);
beta_trial = zeros(L,1);
n_pks = length(pk_loc);
aux_x = x;
% Start with clear peaks
for i = 1:n_pks
if pk_loc(i) - round(M/2) <= 0
idx = 1:pk_loc(i) + round(M/2) - 1;
x_norm = [zeros(1, M - length(idx)) x(idx)];
elseif pk_loc(i) + round(M/2) - 1 > N
idx = pk_loc(i) - round(M/2):N;
x_norm = [x(idx) zeros(1, M - length(idx))];
else
idx = pk_loc(i) - round(M/2):pk_loc(i) + round(M/2) - 1;
x_norm = x(idx);
end
beta_trial(i,1) = norm(x_norm);
X_M_snippet(:,i) = x_norm';
aux_x(idx) = zeros(1,length(idx));
end
i = i + 1;
while stp_fl == 0
% Check if there are any M-snippets left to be discovered
[tau_p, fl] = check_potential_seg(aux_x, M);
if fl == 0
for j = 1:length(tau_p)
idx = tau_p(j):tau_p(j) + M - 1;
X_M_snippet(:,i) = x(idx)';
beta_trial(i,1) = norm(x(idx));
aux_x(idx) = zeros(1,length(idx));
i = i + 1;
end
else
stp_fl = 1;
end
end
beta_trial = beta_trial(1:i-1,1);
X_M_snippet = X_M_snippet(:,i-1);
% % Optional - Not really necessary when trials are long, besides these
% % norms would not have a direct mapping to M-snippets in x
% % Put together all the remaining unconnected temporal samples and compute
% % norm
% x_rem = aux_x(aux_x ~= 0);
% n_rem = floor(length(x_rem)/M);
% beta_rem = zeros(n_rem,1);
% if n_rem > 0
% for i = 1:n_rem
% beta_rem(i) = norm(x_rem((i-1)*M+1:i*M));
% end
% beta_trial = [beta_trial; beta_rem];
% end
end
%%
function [tau_p, fl] = check_potential_seg(aux_x, M)
% INPUTS:
% aux_x - Single-channel, single-trial bandpassed EEG trace after removing
% already discovered M-snippets
% M - Dimensionality of embedding, i.e. duration (in samples) of putative
% events
% OUTPUTS:
% tau_p - Timestamps of M-snippets left to be extracted/discovered
% fl - Flag to determine end of search
% if fl = 0 -> no M-snippets left to be found
% if fl = 1 -> M-snippets still available
max_tau_ones = double((aux_x ~= 0));
aux_fl = conv(max_tau_ones,ones(1,M),'valid');
idx = find(aux_fl == M);
if isempty(idx) == 1
fl = 1;
tau_p = 0;
else
fl = 0;
aux_idx = find(diff(idx) >= M) + 1;
tau_p = [idx(1) idx(aux_idx)];
end
end