-
Notifications
You must be signed in to change notification settings - Fork 14
/
osl_cov.m
150 lines (117 loc) · 4.3 KB
/
osl_cov.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
function [C,M] = osl_cov(D)
% Computes the covariance of a [channels x samples] matrix without
% encountering memory issues. This allows the covariance matrix to be
% computed for large data matrices without running out of memory.
%
% This function can also compute the (channels x channels x trials) covariance
% matrix of a (channelx x samples x trials) MEEG object (using only good
% samples).
%
% Usage:
% C = osl_cov(D)
%
% [C,M] = osl_cov(D) also returns the mean
%
% Adam Baker 2014
%{
% PROTOTYPE CODE
% FOR FUTURE WORK
%
% The idea is that you can compute source space voxel covariance by getting
% the sensor covariance, C_s, and then transforming it by tra. That is, for M_s and C_s in source space,
% the sensor space corresponding outputs M and C are
% M = tra*M_s
% C = tra*C_s*tra'
% This is way faster and will do away with memory issues in source space. But implementation should ideally be done when
% this function is encountered in production
function [C,M] = osl_cov(D,chaninds)
if nargin < 2 || isempty(chaninds)
chaninds = [];
end
samples2use = good_samples(D,chaninds); % Check all good channels by default - this will be sensible in source space. In sensor space, probably better to just compute cov directly?
if D.montage('getindex')
montaged=true
mont = D.montage('getmontage');
D = D.montage('switch',0);
M = mont.tra*q2;
else
montaged = false
end
dat = D(:,:,:); % Read in sensor data
M = zeros(D.nchannels,D.ntrials,D.nfrequencies);
C = zeros(D.nchannels,D.nchannels,D.ntrials,D.nfrequencies);
for j = 1:nfreqs
for k = 1:ntrials
if any(samples2use(:,k))
if isa(D,'meeg') && isequal(D.transformtype,'TF')
C(:,:,k,f) = cov(dat(:,:,k,j)) % Or something like this, depends on what a TF MEEG looks like??
M() = mean()
else
C(:,:,k,f) = cov(dat(:,:,k))
M() = mean()
end
end
end
end
if montaged
% Apply tra
% Need to loop this over frequencies and trials
M = mont.tra*M
C=mont.tra*C*mont.tra';
end
%}
if isa(D,'meeg')
nfreqs = max([1,D.nfrequencies]);
nchans = D.nchannels;
ntrials = D.ntrials;
samples2use = good_samples(D);
else
[nchans,nsamples] = size(D);
ntrials = 1;
nfreqs = 1;
if nchans > nsamples
warning(['Input has ' num2str(nsamples) ' rows and ' num2str(nchans) ' columns. Consider transposing']);
end
samples2use = true(1,nsamples,1);
end
M = zeros(nchans,ntrials,nfreqs);
C = zeros(nchans,nchans,ntrials,nfreqs);
for f = 1:nfreqs
for trl = 1:ntrials
nsamples = sum(samples2use(1,:,trl));
if nsamples,
% Compute means
chan_blks = osl_memblocks([nchans,sum(samples2use(1,:,trl))],1);
for i = 1:size(chan_blks,1)
if isa(D,'meeg') && isequal(D.transformtype,'TF')
Dblk = D(chan_blks(i,1):chan_blks(i,2),f,:,trl);
Dblk = Dblk(:,:,samples2use(1,:,trl));
else
Dblk = D(chan_blks(i,1):chan_blks(i,2),:,trl);
Dblk = Dblk(:,samples2use(1,:,trl));
end
Dblk = squeeze(Dblk);
M(chan_blks(i,1):chan_blks(i,2),trl,f) = mean(Dblk,2);
end
% Compute covariance
smpl_blks = osl_memblocks([nchans,nsamples],2);
for i = 1:size(smpl_blks,1)
samples2use_blk = find(samples2use(1,:,trl));
samples2use_blk = samples2use_blk(1,smpl_blks(i,1):smpl_blks(i,2));
if isa(D,'meeg') && isequal(D.transformtype,'TF')
Dblk = squeeze(D(:,f,:,trl));
Dblk = Dblk(:,samples2use_blk);
else
Dblk = D(:,:,trl);
Dblk = Dblk(:,samples2use_blk);
end
Dblk = bsxfun(@minus,Dblk,M(:,trl,f));
C(:,:,trl,f) = C(:,:,trl,f) + Dblk*Dblk';
end
C(:,:,trl,f) = C(:,:,trl,f)./(nsamples-1);
else % trial is bad or empty
C(:,:,trl,f) = zeros(nchans);
end
end
end
end