forked from OHBA-analysis/osl-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
osl_merge_first_levels.m
120 lines (98 loc) · 5.67 KB
/
osl_merge_first_levels.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
function [oat] = firstLevelSessCombine(sessionInds,oat)
%
% [oat] = firstLevelSessCombine(sessionInds,oat)
%
% Takes a cell array of first-level result file indices grouped by subject,
% i.e.
% {[1,2],[3,4],...etc} if 2 sessions per subject, and combines the
% session-wise first level GLMs into a subject-wise first level GLM using
% flame1
% note that resultscope here are:
% num_tpts x num_firstlevel_contrasts x num_freqs x num_sessions
% ...and the GLM fitted by flame1 is computing an average over sessions
results_fnames = cell(numel(sessionInds),1);
for iSub = 1:numel(sessionInds)
xnew = [];
% get the first_level data
for iSess = 1:numel(sessionInds{iSub})
fname = oat.first_level.results_fnames{sessionInds{iSub}(iSess)};
tmp = load([oat.source_recon.dirname '/' fname]);
res_strct(iSess).res = tmp.oat_stage_results;
xnew = [xnew ; res_strct(iSess).res.x];
% delete the session-wise first level files once the data is
% extracted from them
delete([oat.source_recon.dirname '/' fname '.mat']);
end % for iSess = 1:numel(sessionIndices{iSub})
% get the number of voxels, times, freqs, sessions
nVox = numel(res_strct(1).res.mask_indices_in_source_recon);
nTimes = numel(res_strct(1).res.times);
nFreqs = numel(res_strct(1).res.frequencies);
nContrasts = numel(res_strct(1).res.contrasts);
nSessions = numel(sessionInds{iSub});
% make containers
first_level_results.cope = nan(nVox,nTimes,nContrasts,nFreqs);
first_level_results.stdcope = nan(nVox,nTimes,nContrasts,nFreqs);
% voxel loop
ft_progress('init', 'etf');
for iVox = 1:nVox
ft_progress(iVox/nVox);
% time loop
for iTime = 1:nTimes
% contrast loop
for iContrast = 1:nContrasts
% freq loop
for iFreq = 1:nFreqs
% session loop to concatenate sessions
resultscope = nan(nTimes,nContrasts,nFreqs,nSessions);
resultsstdcope = nan(nTimes,nContrasts,nFreqs,nSessions);
for iSess = 1:numel(sessionInds{iSub})
if nFreqs == 1;
resultscope(iTime,iContrast,iFreq,iSess) = res_strct(iSess).res.cope(iVox,iTime,iContrast);
resultsstdcope(iTime,iContrast,iFreq,iSess) = res_strct(iSess).res.stdcope(iVox,iTime,iContrast);
else
resultscope(iTime,iContrast,iFreq,iSess) = res_strct(iSess).res.cope(iVox,iTime,iContrast,iFreq);
resultsstdcope(iTime,iContrast,iFreq,iSess) = res_strct(iSess).res.stdcope(iVox,iTime,iContrast,iFreq);
end
end % for iSess = 1:numel(sessionInds{iSub})
cope=permute(resultscope(iTime,iContrast,iFreq,:),[4 1 2 3]);
stdcope=permute(resultsstdcope(iTime,iContrast,iFreq,:),[4 1 2 3]);
S=stdcope.^2;
z=ones(size(S,1),1);
[gam, ~, covgam] = flame1(cope,z,S,1);
first_level_results.cope(iVox,iTime,iContrast,iFreq)=gam;
first_level_results.stdcope(iVox,iTime,iContrast,iFreq)=sqrt(covgam);
end % for iFreq = 1:nFreqs
end % for iContrast = 1:nContrasts
end % for iTime = 1:nTimes
end % for iVox = 1:nVox
ft_progress('close');
% save the new first level results
% first_level_results.cope already specified
% first_level_results.stdcope already specified
first_level_results.mask_indices_in_source_recon = res_strct(1).res.mask_indices_in_source_recon; % does this differ between sensor and source space, or can it be set the same way here?
first_level_results.times = res_strct(1).res.times;
first_level_results.frequencies = res_strct(1).res.frequencies;
% (stdcope,cope, set above)
first_level_results.pseudo_zstat_var = res_strct(1).res.psudo_zstat_var; % probably wrong?
first_level_results.D_sensor_data = res_strct(1).res.D_sensor_data; % almost certainly wrong?
first_level_results.chanind = res_strct(1).res.chanind; % probably only for a sensor level analysis - wrap in a conditional?
first_level_results.x = xnew;
first_level_results.contrasts = res_strct(1).res.contrasts;
first_level_results.source_recon_results_fname = res_strct(1).res.source_recon_results_fname;
first_level_results.S = res_strct(1).res.S;
first_level_results.bf_S = res_strct(1).res.bf_S;
first_level_results.level = res_strct(1).res.level;
first_level_results.name = res_strct(1).res.name;
first_level_results.recon_method = res_strct(1).res.recon_method;
% will gridstep need to be specified for source space?
if isfield(res_strct(1).res,'mni_coord') % is this still a field for beamformed data?
first_level_results.mni_coord = res_strct(1).res.mni_coord;
end
first_level_results.subject_name = ['subject' num2str(iSub)];
first_level_results.fname=[ first_level_results.subject_name '_' first_level_results.name ];
disp(['Saving session-concatenated statistics in file ' oat.name '/' first_level_results.fname]);
oat_save_results( oat, first_level_results );
results_fnames{iSub}=first_level_results.fname;
end % for iSub = 1:numel(sessionInds)
% update oat.first_level
oat.first_level.results_fnames = results_fnames;