Skip to content

Commit f424273

Browse files
committed
FIX - MEEG: epoch reporting with heterogeneous data
1 parent 6094ce3 commit f424273

1 file changed

Lines changed: 32 additions & 28 deletions

File tree

aa_modules/aamod_meeg_epochs.m

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
outfname = outfname(strcmp(spm_file(outfname,'ext'),'set'));
1313
segments = reshape(str2double(unique(regexp(spm_file(outfname,'basename'),'(?<=seg-)[0-9]+','match','once'))),1,[]);
1414
conds = regexp(spm_file(outfname(endsWith(spm_file(outfname,'basename'),'seg-1')),'basename'),'(?<=_)[A-Z-0-9]+','match','once');
15-
condnum = cellfun(@(x) str2double(regexp(x,'(?<=-)[0-9]+','match')), conds);
15+
condname = cellfun(@(x) regexp(x,'[a-zA-Z0-9]+(?=-)','match','once'), conds, 'UniformOutput', false);
16+
condnum = cellfun(@(x) str2double(regexp(x,'(?<=-)[0-9]+','match')), conds);
1617

1718
% init summary
1819
% - first session
@@ -28,7 +29,7 @@
2829
case 'unloaded', EL.reload;
2930
end
3031
for c = 1:numel(conds)
31-
subjtrials{c} = logical(sparse(numel(segments),MAXNTRIAL));
32+
subjtrials.(condname{c}) = logical(sparse(numel(segments),MAXNTRIAL));
3233
for s = segments
3334
segoutfname = outfname(endsWith(spm_file(outfname,'basename'),sprintf('seg-%d',s)));
3435
if numel(segoutfname) ~= numel(conds), aas_log(aap,true,'All segments MUST have all conditions'); end
@@ -42,9 +43,9 @@
4243
utrials = cellfun(@get_eventvalue, {eeg.urevent.type})';
4344
indtrials = cumsum(utrials == condnum(c));
4445

45-
subjtrials{c}(s,indtrials([trials.urevent])) = true;
46+
subjtrials.(condname{c})(s,indtrials([trials.urevent])) = true;
4647
end
47-
subjtrials{c}(:,max(indtrials)+1:end) = [];
48+
subjtrials.(condname{c})(:,max(indtrials)+1:end) = [];
4849
end
4950
EL.unload;
5051

@@ -57,13 +58,13 @@
5758
for c = 1:numel(conds)
5859
ax = nexttile;
5960
hold on
60-
arrayfun(@(s) plot(find(subjtrials{c}(s,:)),-s,'b*','MarkerSize',7), 1:numel(segments))
61+
arrayfun(@(s) plot(find(subjtrials.(condname{c})(s,:)),-s,'b*','MarkerSize',7), 1:numel(segments))
6162
hold off
6263
ylim([-max(segments+0.5),-0.5]); yticks(-max(segments):-1);
6364
if c == 1, yticklabels(arrayfun(@(x) sprintf('segment %d',x),max(segments):-1:1,'UniformOutput',false));
6465
else, yticklabels({});
6566
end
66-
xlim([0 size(subjtrials{c},2)]);
67+
xlim([0 size(subjtrials.(condname{c}),2)]);
6768
title(ax, conds{c});
6869
end
6970
print(f,'-djpeg','-r300',fn);
@@ -73,6 +74,10 @@
7374
aap.report.(aap.tasklist.currenttask.name).alltrials{subj,sess} = subjtrials;
7475

7576
% table
77+
condcount = table(...
78+
'Size',[numel(segments) numel(fieldnames(subjtrials))],...
79+
'VariableNames',fieldnames(subjtrials),...
80+
'VariableTypes',repmat({'single'},1,numel(fieldnames(subjtrials))));
7681
aap = aas_report_add(aap,subj,'<table id="data"><tr>');
7782
aap = aas_report_add(aap,subj,'<th>Segment</th>');
7883
for c = 1:numel(conds)
@@ -82,27 +87,25 @@
8287
for s = segments
8388
aap = aas_report_add(aap,subj,'<tr>');
8489
aap = aas_report_add(aap,subj,sprintf('<td>segment %d</td>',s));
85-
for c = 1:numel(conds)
86-
condcount(s,c) = nnz(subjtrials{c}(s,:));
87-
aap = aas_report_add(aap,subj,sprintf('<td>%d</td>',condcount(s,c)));
90+
for cond = fieldnames(subjtrials)'
91+
condcount.(cond{1})(s) = nnz(subjtrials.(cond{1})(s,:));
92+
aap = aas_report_add(aap,subj,sprintf('<td>%d</td>',condcount.(cond{1})(s)));
93+
if condcount.(cond{1})(s) == 0, condcount.(cond{1})(s) = NaN; end
8894
end
8995
aap = aas_report_add(aap,subj,'</tr>');
9096
end
9197
aap = aas_report_add(aap,subj,'</table>');
92-
condcount(condcount==0) = NaN; % zero epoch should be the ones omitted
9398
aap.report.(aap.tasklist.currenttask.name).condcount{subj,sess} = condcount;
9499

95100
case 'summary'
96101
% missing data
97-
isTrialMissing = cellfun(@isempty, aap.report.(aap.tasklist.currenttask.name).alltrials(:,sess));
98-
isCondcountMissing = cellfun(@(cc) isempty(cc) || (isscalar(cc) && isnan(cc)), aap.report.(aap.tasklist.currenttask.name).condcount(:,sess));
99-
lastSubjCondcount = find(~isCondcountMissing,1,'last');
102+
isSubjMissing = cellfun(@isempty, aap.report.(aap.tasklist.currenttask.name).alltrials(:,sess));
103+
maxCondNum = max(cellfun(@(cc) size(cc,2), aap.report.(aap.tasklist.currenttask.name).condcount(:,sess)));
104+
lastSubjCondcount = find(cellfun(@(cc) size(cc,2)==maxCondNum, aap.report.(aap.tasklist.currenttask.name).condcount(:,sess)),1,'last');
100105

101106
% update conditions and sessions based on the last subject with no missing data
102-
outfname = cellstr(aas_getfiles_bystream(aap,'meeg_session',[lastSubjCondcount sess],'meeg','output'));
103-
outfname = outfname(strcmp(spm_file(outfname,'ext'),'set'));
104-
segments = reshape(str2double(unique(regexp(spm_file(outfname,'basename'),'(?<=seg-)[0-9]+','match','once'))),1,[]);
105-
conds = regexp(spm_file(outfname(endsWith(spm_file(outfname,'basename'),'seg-1')),'basename'),'(?<=_)[A-Z-0-9]+','match','once');
107+
segments = 1:size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},1);
108+
conds = aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess}.Properties.VariableNames;
106109

107110
if ~isfield(aap.report.(aap.tasklist.currenttask.name),'summarysessions')
108111
[~, aap.report.(aap.tasklist.currenttask.name).summarysessions] = aas_getN_bydomain(aap,aap.tasklist.currenttask.domain,lastSubjCondcount);
@@ -119,12 +122,12 @@
119122
aap = aas_report_add(aap,'er',['<h3>Session: ' aap.acq_details.meeg_sessions(sess).name '</h3>']);
120123

121124
% Boxplot for each condition
122-
jitter = 0.1; % jitter around position
125+
jitter = 0.1; % jitter around position (for every possible)
123126
jitter = (...
124-
1+(rand([sum(~isCondcountMissing),size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},1)])-0.5) .* ...
125-
repmat(jitter*2./[1:size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},1)],sum(~isCondcountMissing),1)...
127+
1+(rand([numel(isSubjMissing),numel(segments)])-0.5) .* ...
128+
repmat(jitter*2./segments,numel(isSubjMissing),1)...
126129
) .* ...
127-
repmat([1:size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},1)],sum(~isCondcountMissing),1);
130+
repmat(segments,numel(isSubjMissing),1);
128131

129132
condcountFn = fullfile(aas_getstudypath(aap),['diagnostic_' mfilename '_' aap.acq_details.meeg_sessions(sess).name '_conditioncount.jpg']);
130133
condcountFig = figure; condcountFig.Position = [0 0 200*numel(conds) 600*numel(segments)];
@@ -134,18 +137,19 @@
134137
trialcountFig = figure; trialcountFig.Position = [0 0 1080 100*numel(conds)];
135138
tiledlayout(trialcountFig,numel(conds),1,'TileSpacing','tight');
136139

137-
for c = 1:size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},2)
140+
for c = 1:numel(conds)
141+
isCondcountMissing = cellfun(@(cc) isempty(cc) || ~any(strcmp(conds{c},cc.Properties.VariableNames)), aap.report.(aap.tasklist.currenttask.name).condcount(:,sess));
138142
figure(condcountFig); ax = nexttile; hold on;
139-
boxplot(cell2mat(cellfun(@(cc) cc(:,c), aap.report.(aap.tasklist.currenttask.name).condcount(~isCondcountMissing,sess), 'UniformOutput', false)')',...
143+
boxplot(cell2mat(cellfun(@(cc) cc.(conds{c})(:), aap.report.(aap.tasklist.currenttask.name).condcount(~isCondcountMissing,sess), 'UniformOutput', false)')',...
140144
'label',arrayfun(@(x) sprintf('Segment %d',x), 1:size(aap.report.(aap.tasklist.currenttask.name).condcount,3), 'UniformOutput', false));
141-
for seg = 1:size(aap.report.(aap.tasklist.currenttask.name).condcount{lastSubjCondcount,sess},1)
142-
scatter(jitter(:,seg),cellfun(@(cc) cc(seg,c), aap.report.(aap.tasklist.currenttask.name).condcount(~isCondcountMissing,sess)),'k','filled','MarkerFaceAlpha',0.4);
145+
for seg = segments
146+
scatter(jitter(~isCondcountMissing,seg),cellfun(@(cc) cc.(conds{c})(seg), aap.report.(aap.tasklist.currenttask.name).condcount(~isCondcountMissing,sess)),'k','filled','MarkerFaceAlpha',0.4);
143147
end
144148
boxValPlot{c} = getappdata(getappdata(gca,'boxplothandle'),'boxvalplot');
145149
title(ax,conds{c});
146150

147151
figure(trialcountFig); ax = nexttile;
148-
tmp = cellfun(@(trl) full(trl{c}), aap.report.(aap.tasklist.currenttask.name).alltrials(~isTrialMissing,sess), 'UniformOutput', false);
152+
tmp = cellfun(@(trl) full(trl.(conds{c})), aap.report.(aap.tasklist.currenttask.name).alltrials(~isCondcountMissing,sess), 'UniformOutput', false);
149153
maxNTrials = max(cellfun(@numel, tmp));
150154
for su = 1:numel(tmp)
151155
tmp{su}(end+1:maxNTrials) = false;
@@ -176,7 +180,7 @@
176180
aap = aas_report_add(aap,'er',sprintf('<th>Outliers</th>'));
177181
end
178182
aap = aas_report_add(aap,'er','</tr>');
179-
for seg = 1:size(aap.report.(aap.tasklist.currenttask.name).condcount{subj,sess},1)
183+
for seg = segments
180184
aap = aas_report_add(aap,'er','<tr>');
181185
aap = aas_report_add(aap,'er',sprintf('<td>segment %d</td>',seg));
182186
for c = 1:numel(conds) % for each condition
@@ -338,7 +342,7 @@
338342
else
339343
missingEp = arrayfun(@(ep) isempty(ep.eventtype) || ~any(strcmp(cellstr(ep.eventtype), ev.eventvalue)), epochEEG.epoch);
340344
end
341-
if any(missingEp)
345+
if size(epochEEG.data,3) > 1 && any(missingEp)
342346
% - insert marking event into the middle of the trial
343347
mEEG = segEEG;
344348
deltaLat = (ev.trlshift + mean(ev.eventwindow))/1000*mEEG.srate;

0 commit comments

Comments
 (0)