Skip to content

Commit 8cf179d

Browse files
committed
Fix TAM preprocessing and standard condition handling
1 parent ad8973f commit 8cf179d

3 files changed

Lines changed: 381 additions & 71 deletions

File tree

‎src/pspm_check_model.m‎

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -441,22 +441,20 @@
441441
' index corresponding to it.'];
442442
if ~isfield(model,'std_exp_cond')
443443
model.std_exp_cond = 'none';
444-
elseif ~ischar(model.std_exp_cond) && ~isnumeric(model.std_exp_cond)
445-
warning('ID:invalid_input',std_cond_war_msg); return;
446444
elseif ischar(model.std_exp_cond)
447-
tmp_ind = cellfun(@(x) strcmpi(model.std_exp_cond,x), model.timing{1}.names);
448-
if ~any(tmp_ind)
449-
warning('ID:invalid_input',std_cond_war_msg); return;
450-
end
451-
std_exp_cond.name = model.std_exp_cond;
452-
std_exp_cond.ind = find(tmp_ind);
445+
% 'none' is explicitly allowed
446+
if ~strcmpi(model.std_exp_cond, 'none')
447+
tmp_ind = strcmpi(model.std_exp_cond, model.timing{1}.names);
448+
if ~any(tmp_ind); warning('ID:invalid_input', std_cond_war_msg); return; end
449+
end
453450
elseif isnumeric(model.std_exp_cond)
454-
if model.std_exp_cond < 1 || ...
455-
model.std_exp_cond > numel(model.timing{1}.names)
456-
warning('ID:invalid_input',std_cond_war_msg); return;
457-
end
458-
std_exp_cond.name = model.timing{1}.names(model.std_exp_cond);
459-
std_exp_cond.ind = model.std_exp_cond;
451+
% Must be one valid scalar integer index
452+
if ~isscalar(model.std_exp_cond) || ~isfinite(model.std_exp_cond) || ...
453+
model.std_exp_cond < 1 || model.std_exp_cond > numel(model.timing{1}.names)
454+
warning('ID:invalid_input', std_cond_war_msg); return;
455+
end
456+
else
457+
warning('ID:invalid_input',std_cond_war_msg); return;
460458
end
461459
clear std_cond_war_msg tmp_ind
462460

‎src/pspm_tam.m‎

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
% ├─────.timing: a multiple condition file name (single session) OR
1313
% │ a cell array of multiple condition file names OR
1414
% │ a struct (single session) with fields .names, .onsets,
15-
% │ and (optional) .durations OR
15+
% │ and (optional) duration OR
1616
% │ a cell array of struct OR
1717
% │ a struct with fields 'markerinfos', 'markervalues',
1818
% │ 'names' OR
@@ -83,6 +83,7 @@
8383
% Introduced In PsPM 4.2
8484
% Written in 2020 by Ivan Rojkov (University of Zurich)
8585
% Maintained in 2022 by Teddy
86+
% Maintained in 2026 by Bernhard A. von Raußendorf
8687
% ● Developer
8788
% The fitting process is a residual least square minimisation where the
8889
% predicted value is calculated as following:
@@ -126,6 +127,18 @@
126127
return
127128
end
128129

130+
% 2.3 check ....
131+
std_exp_cond = [];
132+
133+
if ~(ischar(model.std_exp_cond) && strcmpi(model.std_exp_cond, 'none'))
134+
if ischar(model.std_exp_cond)
135+
std_exp_cond.ind = find(strcmpi( model.std_exp_cond, model.timing{1}.names), 1);
136+
else
137+
std_exp_cond.ind = model.std_exp_cond;
138+
end
139+
std_exp_cond.name = model.timing{1}.names{std_exp_cond.ind};
140+
end
141+
129142
%% Loading files
130143

131144
fprintf('Computing Trial Average Model: %s \n', model.modelfile);
@@ -163,7 +176,7 @@
163176
% Checking if the sampling rate is the same for all samples.
164177
if n_file > 1 && any(diff(sr) ~= 0) % not any(diff(sr) > 0)
165178
if (ischar(model.filter.down) && strcmpi(model.filter.down, 'none')) || ... % if filter.down is none
166-
(isnumeric(model.filter.down) && model.filter.down > min(sr)) % if filter.down is less than the minimal sr
179+
(isnumeric(model.filter.down) && model.filter.down > min(sr)) % if filter.down is less than the minimal sr
167180

168181
model.filter.down = min(sr);
169182
fprintf('\nSampling rate differs between sessions. Data will be downsampled.\n')
@@ -202,7 +215,7 @@
202215
tmp_data.mean = s.segments{i,1}.mean; % why not eg 50x1
203216
tmp_data.std = s.segments{i,1}.std;% why not eg 50x1
204217
tmp_data.sem = s.segments{i,1}.sem;% why not eg 50x1
205-
tmp_data.t = s.segments{i,1}.t;
218+
tmp_data.t = s.segments{i,1}.t; %
206219
% a cell array of struct and of size (n_file x n_exp_cond) where each
207220
% line correspond to a given file and each column to an
208221
% experimental condition
@@ -215,33 +228,44 @@
215228

216229
%% Downsample the data
217230
% if a filter was specified or if the data differ in sr
218-
fprintf('Filtering ...\n')
219-
for i = 1:n_exp_cond
220-
for k = 1:n_file
221231

222-
model.filter.sr = sr(k);
232+
fprintf('Filtering ...\n') % maybe only if there is a filtering?
223233

224-
[lsts, segm{k,i}, ~] = structfun(@(x) pspm_prepdata(x, model.filter),segm{k,i},'UniformOutput',false);
225-
if any(structfun(@(x) x<1,lsts)), warning('ID:error_prepdata','An error occured in pspm_prepdata.'); return; end
226234

227-
clear new_sr lsts
235+
fields = {'mean', 'std', 'sem'};
236+
for i = 1:n_exp_cond
237+
for k = 1:n_file
238+
model.filter.sr = sr(k); % adds the corresponding sr to the filer
239+
240+
for f = 1:numel(fields)
241+
field = fields{f};
242+
[lsts, segm{k,i}.(field), new_sr(k)] = pspm_prepdata(segm{k,i}.(field), model.filter);
243+
if lsts < 1; warning('ID:error_prepdata', 'An error occured in pspm_prepdata.'); return; end
244+
end
245+
[llsts, segm{k,i}.t , new_sr(k) ] = pspm_downsample(segm{k,i}.t, sr(k), new_sr(k) ); % does not need to be filtered!
246+
if llsts < 1; warning('ID:error_downsample', 'An error occured in pspm_downsample.'); return; end
247+
228248
end
229249
end
230250

231-
% changing the sampling rate
232-
if isnumeric(model.filter.down)
233-
sr = model.filter.down * ones(size(sr)); % needs to be tested
234-
end
251+
sr = new_sr; % maybe test upstream if all new_sr are the same!
252+
% % changing the sampling rate
253+
% if isnumeric(model.filter.down)
254+
% sr = model.filter.down * ones(size(new_sr)); % needs to be tested why not the values of prepdata?
255+
% end
256+
257+
clear new_sr
235258

236259
%% Determining mean values
237260
fprintf('Preparing for fitting ...\n')
238261

239262
baseline_index = floor(sr(1)*model.baseline)+1;
240263

241-
if exist('std_exp_cond','var')
264+
265+
if ~isempty(std_exp_cond)
242266
tmp_data = [segm{:,std_exp_cond.ind}];
243267

244-
std_exp_cond.data = mean([tmp_data.mean],2, 'omitnan'); %nanmean([tmp_data.mean],2);
268+
std_exp_cond.data = mean([tmp_data.mean],2, 'omitnan');
245269
std_exp_cond.std = mean([tmp_data.std],2, 'omitnan');
246270
std_exp_cond.sem = mean([tmp_data.sem],2, 'omitnan');
247271
end
@@ -256,7 +280,7 @@
256280
tmp_data_new.t = mean([tmp_data.t],2, 'omitnan');
257281

258282
% Subtracting the standard experimental condition
259-
if exist('std_exp_cond','var') && i~=std_exp_cond.ind
283+
if ~isempty(std_exp_cond) && i~=std_exp_cond.ind
260284
tmp_data_new.data = tmp_data_new.data - std_exp_cond.data;
261285
tmp_data_new.std = tmp_data_new.std + std_exp_cond.std; % the error adds up
262286
tmp_data_new.sem = tmp_data_new.sem + std_exp_cond.sem; % the error adds up
@@ -266,11 +290,12 @@
266290
tmp_data_new.data = tmp_data_new.data - tmp_data_new.data(baseline_index);
267291

268292
% Dividing by the max value
269-
if model.norm_max
270-
[tmp_max,tmp_max_ind] = max(tmp_data_new.data);
293+
if model.norm_max
294+
[tmp_max,tmp_max_ind] = max(tmp_data_new.data); % this does not give us the first peak!!!
295+
% maybe add if tmp_max == 0
271296
tmp_data_new.data = tmp_data_new.data/tmp_max;
272-
tmp_data_new.std = tmp_data_new.std + tmp_data_new.std(tmp_max_ind); % the error adds up
273-
tmp_data_new.sem = tmp_data_new.sem + tmp_data_new.sem(tmp_max_ind); % the error adds up
297+
tmp_data_new.std = tmp_data_new.std + tmp_data_new.std(tmp_max_ind); % the error adds up . why not /abs(tmp_max)
298+
tmp_data_new.sem = tmp_data_new.sem + tmp_data_new.sem(tmp_max_ind); % the error adds up . why not /abs(tmp_max)
274299
end
275300

276301
mean_data{1,i} = tmp_data_new;
@@ -355,7 +380,7 @@
355380
tam.data.normd = model.norm;
356381
tam.data.norm = model.norm;
357382

358-
if exist('std_exp_cond','var')
383+
if ~isempty(std_exp_cond)
359384
tam.data.std_exp_cond.name = std_exp_cond.name;
360385
tam.data.std_exp_cond.ind = std_exp_cond.ind;
361386
else

0 commit comments

Comments
 (0)