Skip to content

Commit f0a7753

Browse files
committed
refactor
1 parent c65c09e commit f0a7753

File tree

1 file changed

+94
-108
lines changed

1 file changed

+94
-108
lines changed

src/subject_level/convertOnsetTsvToMat.m

Lines changed: 94 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -41,149 +41,98 @@
4141

4242
%
4343
[pth, file, ext] = spm_fileparts(tsvFile);
44-
tsvFile = validationInputFile(pth, [file, ext]);
44+
tsv.file = validationInputFile(pth, [file, ext]);
4545

46-
tsvContent = bids.util.tsvread(tsvFile);
46+
tsv.content = bids.util.tsvread(tsv.file);
4747

48-
if ~all(isnumeric(tsvContent.onset))
48+
if ~all(isnumeric(tsv.content.onset))
4949

5050
errorID = 'onsetsNotNumeric';
51-
msg = sprintf('%s\n%s', 'Onset column contains non numeric values in file:', tsvFile);
51+
msg = sprintf('%s\n%s', 'Onset column contains non numeric values in file:', tsv.file);
5252
errorHandling(mfilename(), errorID, msg, false, opt.verbosity);
5353

5454
end
5555

56-
if ~all(isnumeric(tsvContent.duration))
56+
if ~all(isnumeric(tsv.content.duration))
5757

5858
errorID = 'durationsNotNumeric';
59-
msg = sprintf('%s\n%s', 'Duration column contains non numeric values in file:', tsvFile);
59+
msg = sprintf('%s\n%s', 'Duration column contains non numeric values in file:', tsv.file);
6060
errorHandling(mfilename(), errorID, msg, false, opt.verbosity);
6161

6262
end
6363

64-
variablesToConvolve = opt.model.bm.getVariablesToConvolve();
64+
varToConvolve = opt.model.bm.getVariablesToConvolve();
6565
designMatrix = opt.model.bm.getBidsDesignMatrix();
6666
designMatrix = removeIntercept(designMatrix);
6767

68-
% create empty cell to be filled in according to the conditions present in each run
69-
names = {};
70-
onsets = {};
71-
durations = {};
72-
pmod = struct('name', {''}, 'param', {}, 'poly', {});
68+
% conditions to be filled in according to the conditions present in each run
69+
condToModel.names = {};
70+
condToModel.onsets = {};
71+
condToModel.durations = {};
72+
condToModel.pmod = struct('name', {''}, 'param', {}, 'poly', {});
73+
condToModel.idx = 1;
7374

7475
if ~isfield(opt.model, 'bm')
7576
opt.model.bm = BidsModel('file', opt.model.file);
7677
end
7778
% TODO get / apply transformers from a specific node
7879
transformers = opt.model.bm.getBidsTransformers();
79-
tsvContent = bids.transformers(transformers, tsvContent);
80+
tsv.content = bids.transformers(transformers, tsv.content);
8081

81-
conditionIdx = 1;
82-
83-
for iCond = 1:numel(variablesToConvolve)
82+
for iVar = 1:numel(varToConvolve)
8483

8584
trialTypeNotFound = false; % should be dead code by now
8685
variableNotFound = false;
8786
extra = '';
8887

8988
% first assume the input is from events.tsv
90-
tokens = regexp(variablesToConvolve{iCond}, '\.', 'split');
89+
tokens = regexp(varToConvolve{iVar}, '\.', 'split');
9190

9291
% if the variable is present in namespace
93-
if ismember(tokens{1}, fieldnames(tsvContent))
92+
if ismember(tokens{1}, fieldnames(tsv.content))
9493

95-
if ~ismember(variablesToConvolve{iCond}, designMatrix)
94+
if ~ismember(varToConvolve{iVar}, designMatrix)
9695
% TODO does not account for edge cases where design matrix uses globbing pattern
9796
% like "face_*"
9897
% but variablesToConvolve only includes a subset of conditions
9998
% like "face_1" but not "face_2"
10099
continue
101100
end
102101

103-
trialTypes = tsvContent.(tokens{1});
104-
conditionName = strjoin(tokens(2:end), '.');
102+
trialTypes = tsv.content.(tokens{1});
103+
condName = strjoin(tokens(2:end), '.');
105104

106105
% deal with any globbing search like 'face_familiar*'
107-
hasGlobPattern = ~cellfun('isempty', regexp({conditionName}, '\*|\?'));
106+
hasGlobPattern = ~cellfun('isempty', regexp({condName}, '\*|\?'));
108107

109-
if any(hasGlobPattern)
108+
if hasGlobPattern
110109

111-
pattern = strrep(conditionName, '*', '[\_\-0-9a-zA-Z]*');
110+
pattern = strrep(condName, '*', '[\_\-0-9a-zA-Z]*');
112111
pattern = strrep(pattern, '?', '[0-9a-zA-Z]?');
113112
pattern = regexify(pattern);
114113
containsPattern = ~cellfun('isempty', regexp(trialTypes, pattern));
115114

116-
conditionsList = unique(trialTypes(containsPattern));
117-
118-
for iCdt = 1:numel(conditionsList)
119-
120-
rows = find(strcmp(conditionsList{iCdt}, trialTypes));
121-
122-
printToScreen(sprintf(' Condition %s: %i trials found.\n', ...
123-
conditionsList{iCdt}, ...
124-
numel(rows)), ...
125-
opt);
126-
127-
if ~isempty(rows)
128-
129-
names{1, conditionIdx} = conditionsList{iCdt};
130-
onsets{1, conditionIdx} = tsvContent.onset(rows)'; %#ok<*AGROW,*NASGU>
131-
durations{1, conditionIdx} = tsvContent.duration(rows)';
132-
pmod = parametricModulation(pmod, tsvContent, rows, conditionIdx);
133-
134-
conditionIdx = conditionIdx + 1;
135-
136-
else
137-
138-
trialTypeNotFound = true;
139-
errorID = 'trialTypeNotFound';
140-
input1 = 'Trial type';
115+
condList = unique(trialTypes(containsPattern));
141116

142-
msg = sprintf('%s %s not found in \n %s\n %s', ...
143-
input1, ...
144-
variablesToConvolve{iCond}, ...
145-
tsvFile, ...
146-
extra);
117+
for iCdt = 1:numel(condList)
147118

148-
errorHandling(mfilename(), errorID, msg, true, opt.verbosity);
149-
150-
end
119+
condToModel = addCondition(opt, ...
120+
condList{iCdt}, ...
121+
trialTypes, ...
122+
tsv, ...
123+
condToModel, ...
124+
varToConvolve{iVar});
151125

152126
end
153127

154128
else
155129

156-
rows = find(strcmp(conditionName, trialTypes));
157-
158-
printToScreen(sprintf(' Condition %s: %i trials found.\n', ...
159-
conditionName, ...
160-
numel(rows)), ...
161-
opt);
162-
163-
if ~isempty(rows)
164-
165-
names{1, conditionIdx} = conditionName;
166-
onsets{1, conditionIdx} = tsvContent.onset(rows)'; %#ok<*AGROW,*NASGU>
167-
durations{1, conditionIdx} = tsvContent.duration(rows)';
168-
pmod = parametricModulation(pmod, tsvContent, rows, conditionIdx);
169-
170-
conditionIdx = conditionIdx + 1;
171-
172-
else
173-
174-
trialTypeNotFound = true;
175-
errorID = 'trialTypeNotFound';
176-
input1 = 'Trial type';
177-
178-
msg = sprintf('%s %s not found in \n %s\n %s', ...
179-
input1, ...
180-
variablesToConvolve{iCond}, ...
181-
tsvFile, ...
182-
extra);
183-
184-
errorHandling(mfilename(), errorID, msg, true, opt.verbosity);
185-
186-
end
130+
condToModel = addCondition(opt, ...
131+
condName, ...
132+
trialTypes, ...
133+
tsv, ...
134+
condToModel, ...
135+
varToConvolve{iVar});
187136

188137
end
189138

@@ -195,19 +144,16 @@
195144

196145
end
197146

198-
if variableNotFound || trialTypeNotFound
147+
if variableNotFound
199148

200149
if opt.glm.useDummyRegressor
201-
[names, onsets, durations] = addDummyRegressor(names, onsets, durations);
202-
extra = 'Adding dummy regressor instead.';
203-
conditionIdx = conditionIdx + 1;
150+
condToModel = addDummyRegressor(condToModel);
204151
end
205152

206-
msg = sprintf('%s %s not found in \n %s\n %s', ...
153+
msg = sprintf('%s %s not found in \n %s\n Adding dummy regressor instead.', ...
207154
input1, ...
208-
variablesToConvolve{iCond}, ...
209-
tsvFile, ...
210-
extra);
155+
varToConvolve{iVar}, ...
156+
tsv.file);
211157

212158
errorHandling(mfilename(), errorID, msg, true, opt.verbosity);
213159

@@ -216,51 +162,91 @@
216162
end
217163

218164
%% save the onsets as a matfile
219-
[pth, file] = spm_fileparts(tsvFile);
165+
[pth, file] = spm_fileparts(tsv.file);
220166

221167
bf = bids.File(file);
222168
bf.suffix = 'onsets';
223169
bf.extension = '.mat';
224170

225171
fullpathOnsetFilename = fullfile(pth, bf.filename);
226172

173+
names = condToModel.names; %#ok<*NASGU>
174+
onsets = condToModel.onsets;
175+
durations = condToModel.durations;
176+
pmod = condToModel.pmod;
177+
227178
save(fullpathOnsetFilename, ...
228179
'names', 'onsets', 'durations', 'pmod', ...
229180
'-v7');
230181

231182
end
232183

233-
function pmod = parametricModulation(pmod, tsvContent, rows, conditionIdx)
184+
function condToModel = addCondition(opt, condName, trialTypes, tsv, condToModel, varToConvolve)
185+
186+
rows = find(strcmp(condName, trialTypes));
187+
188+
printToScreen(sprintf(' Condition %s: %i trials found.\n', ...
189+
condName, ...
190+
numel(rows)), ...
191+
opt);
192+
193+
if ~isempty(rows)
194+
195+
condToModel.names{1, condToModel.idx} = condName;
196+
condToModel.onsets{1, condToModel.idx} = tsv.content.onset(rows)';
197+
condToModel.durations{1, condToModel.idx} = tsv.content.duration(rows)';
198+
condToModel = parametricModulation(condToModel, tsv, rows);
199+
200+
condToModel.idx = condToModel.idx + 1;
201+
202+
else
203+
204+
msg = sprintf('Trial type %s not found in \n\t%s\n', ...
205+
varToConvolve, ...
206+
tsv.file);
207+
208+
errorHandling(mfilename(), 'trialTypeNotFound', msg, true, opt.verbosity);
209+
210+
if opt.glm.useDummyRegressor
211+
condToModel = addDummyRegressor(condToModel);
212+
end
213+
214+
end
215+
216+
end
217+
218+
function conditionsToModel = parametricModulation(conditionsToModel, tsv, rows)
234219
% parametric modulation (pmod)
235220
%
236-
% skipped if parametric modulation is 1 for all onsets
221+
% skipped if parametric modulation == 1 for all onsets
237222
%
238223
% coerces NaNs into 1
239224

240-
fields = fieldnames(tsvContent);
225+
fields = fieldnames(tsv.content);
241226
pmodIdx = ~cellfun('isempty', regexp(fields, '^pmod_.*', 'match'));
242227
pmodIdx = find(pmodIdx);
243228

244229
for iMod = 1:numel(pmodIdx)
245230

246231
thisMod = fields{pmodIdx(iMod)};
247232

248-
amplitude = tsvContent.(thisMod)(rows);
233+
amplitude = tsv.content.(thisMod)(rows);
249234
amplitude(isnan(amplitude)) = 1;
250235

251236
if ~all(amplitude == 1)
252-
pmod(1, conditionIdx).name{iMod} = strrep(thisMod, 'pmod_', '');
253-
pmod(end).param{iMod} = amplitude;
254-
pmod(end).poly{iMod} = 1;
237+
conditionsToModel.pmod(1, conditionsToModel.idx).name{iMod} = strrep(thisMod, 'pmod_', '');
238+
conditionsToModel.pmod(end).param{iMod} = amplitude;
239+
conditionsToModel.pmod(end).poly{iMod} = 1;
255240
end
256241

257242
end
258243
end
259244

260-
function [names, onsets, durations] = addDummyRegressor(names, onsets, durations)
245+
function conditionsToModel = addDummyRegressor(conditionsToModel)
261246

262-
names{1, end + 1} = 'dummyRegressor';
263-
onsets{1, end + 1} = nan;
264-
durations{1, end + 1} = nan;
247+
conditionsToModel.names{1, end + 1} = 'dummyRegressor';
248+
conditionsToModel.onsets{1, end + 1} = nan;
249+
conditionsToModel.durations{1, end + 1} = nan;
250+
conditionsToModel.idx = conditionsToModel.idx + 1;
265251

266252
end

0 commit comments

Comments
 (0)