|
190 | 190 | else |
191 | 191 | window_seconds = model.window; |
192 | 192 | end |
193 | | - |
194 | 193 | if any(model.baseline >= window_seconds) % Reject a baseline outside the window in any session. |
195 | 194 | warning('ID:invalid_input', 'Baseline must be smaller than the window duration in seconds.'); |
196 | 195 | return; |
197 | 196 | end |
198 | 197 |
|
| 198 | +% Check for inconsistent window durations across sessions. |
| 199 | +if any(abs(window_seconds - window_seconds(1)) > 1e-10) |
| 200 | + warning('ID:invalid_input', 'Sessions must have the same window duration in seconds.'); |
| 201 | + return; |
| 202 | +end |
| 203 | + |
| 204 | +% Convert one-based sample onsets to seconds for each session. |
| 205 | +if strcmp(model.timeunits, 'samples') |
| 206 | + for k = 1:n_file |
| 207 | + timing{k}.onsets = cellfun( @(onsets) (onsets - 1) / oldsr(k), timing{k}.onsets, 'UniformOutput', false); |
| 208 | + end |
| 209 | +end |
| 210 | + |
| 211 | + |
199 | 212 | % Checking if the sampling rate is the same for all samples. |
200 | 213 | if n_file > 1 && any(diff(sr) ~= 0) % not any(diff(sr) > 0) |
201 | 214 | if (ischar(model.filter.down) && strcmpi(model.filter.down, 'none')) || ... % if filter.down is none |
|
224 | 237 | % temporary structure which is deleted after extracting segments |
225 | 238 | extrsgopt.timeunits = model.timeunits; |
226 | 239 | extrsgopt.length = model.window; % segments of 'model.window' time unit long |
| 240 | + |
| 241 | +% Use seconds for sample onsets that have already been converted. |
| 242 | +if strcmp(model.timeunits, 'samples') |
| 243 | + extrsgopt.timeunits = 'seconds'; |
| 244 | +end |
| 245 | + |
227 | 246 | extrsgopt.plot = 0; % do not plot mean value and std |
228 | 247 | extrsgopt.norm = model.norm; |
229 | 248 |
|
230 | 249 | for k=1:n_file |
| 250 | + % Pass the converted window duration for this session. |
| 251 | + if strcmp(model.timeunits, 'samples') |
| 252 | + extrsgopt.length = window_seconds(k); |
| 253 | + end |
| 254 | + |
231 | 255 | if strcmpi(model.timeunits, 'markers') |
232 | 256 | % marker channel for this session |
233 | 257 | if iscell(options.marker_chan) |
|
281 | 305 | for i = 1:n_exp_cond |
282 | 306 | for k = 1:n_file |
283 | 307 |
|
284 | | - if isempty(segm{k,i}); continue; end % eg. missing condition! |
| 308 | + if isempty(segm{k,i}); continue; end % e.g. missing condition! |
285 | 309 |
|
286 | 310 | model.filter.sr = sr(k); % adds the corresponding sr to the filer |
287 | 311 |
|
|
290 | 314 | [lsts, segm{k,i}.(field), new_sr(k)] = pspm_prepdata(segm{k,i}.(field), model.filter); |
291 | 315 | if lsts < 1; warning('ID:error_prepdata', 'An error occured in pspm_prepdata.'); return; end |
292 | 316 | end |
293 | | - [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! |
294 | | - if llsts < 1; warning('ID:error_downsample', 'An error occured in pspm_downsample.'); return; end |
295 | | - |
| 317 | + |
| 318 | + % Rebuild the time axis from the effective sample rate. |
| 319 | + segm{k,i}.t = (1:numel(segm{k,i}.mean))' / new_sr(k); |
296 | 320 | end |
297 | 321 | end |
298 | 322 |
|
299 | | -sr = new_sr; % maybe test upstream if all new_sr are the same! |
| 323 | +% Check for inconsistent effective sample rates across sessions. |
| 324 | +if any(abs(new_sr - new_sr(1)) > 1e-10) |
| 325 | + warning('ID:invalid_input', 'Sessions must have a common effective sample rate.'); |
| 326 | + return; |
| 327 | +end |
| 328 | +sr = new_sr; |
300 | 329 | % % changing the sampling rate |
301 | 330 | % if isnumeric(model.filter.down) |
302 | 331 | % sr = model.filter.down * ones(size(new_sr)); % needs to be tested why not the values of prepdata? |
|
342 | 371 | end |
343 | 372 |
|
344 | 373 | % Baselining data |
| 374 | + if baseline_index > numel(tmp_data_new.data) || ~isfinite(tmp_data_new.data(baseline_index)) |
| 375 | + warning('ID:invalid_input', 'Baseline sample must be observed and inside the extracted window.'); return; |
| 376 | + end |
345 | 377 | tmp_data_new.data = tmp_data_new.data - tmp_data_new.data(baseline_index); |
346 | 378 |
|
347 | 379 | % Dividing by the max value |
|
364 | 396 | for i=1:n_exp_cond |
365 | 397 | raw_y = mean_data{1,i}.data; |
366 | 398 |
|
367 | | - n = model.window; |
368 | | - td = n / length(raw_y); |
| 399 | + % Use the effective sample rate to define the fitting time grid. |
| 400 | + td = 1 / sr(1); % seconds per sample |
| 401 | + n = numel(raw_y) * td; % length of the window in seconds |
| 402 | + |
369 | 403 |
|
370 | 404 | % Extending the size of the data vector in order to do the fitting, |
371 | 405 | % because if size(raw_y)=[n 1], the convolution would produce a vector of |
|
380 | 414 |
|
381 | 415 | % Minimization of RSS |
382 | 416 | warning off all |
383 | | - [~, fitted{1,i}.optargs, fitted{1,i}.fval, sts, fmincon_output] = ... |
| 417 | + [~, fitted{1,i}.optargs, fitted{1,i}.fval, fsts, fmincon_output] = ... |
384 | 418 | evalc('fmincon(RSS,model.if.args,[],[],[],[],model.if.lb,model.if.ub)'); % lb ub for opt. why not Nelder–Mead / fminsearch.!!?? like in the paper? |
385 | 419 | warning on all |
386 | | - if sts == 0 |
| 420 | + if fsts == 0 |
387 | 421 | warning('ID:fmincon',['During the fitting process, ''fmincon'' exceeded', ... |
388 | 422 | ' the number of iterations or the number of function evaluations.', ... |
389 | 423 | ' Try to change the initial arguments and bounds to improve the fitting.']) |
390 | | - elseif sts == -1 |
| 424 | + elseif fsts == -1 |
391 | 425 | warning('ID:fmincon',['During the fitting process, ''fmincon''', ... |
392 | 426 | ' was terminated by an output function or a plot.']); |
393 | 427 | fprintf('Here is the output of fmincon:\n'); |
394 | 428 | disp(fmincon_output); |
395 | | - elseif sts == -2 |
| 429 | + elseif fsts == -2 |
396 | 430 | warning('ID:fmincon',['During the fitting process, ''fmincon''', ... |
397 | 431 | ' hasn''t found any feasible point.']); |
398 | 432 | fprintf('Here is the output of fmincon:\n'); |
|
450 | 484 | tam.fit.args = {tmp_fitted.optargs}; |
451 | 485 | tam.fit.sr = num2cell(sr(:).'); |
452 | 486 |
|
453 | | -tam.infos.duration = model.window; |
454 | | -tam.infos.durationinfo = 'duration in seconds'; % not always true! -> timeunits='samples' |
| 487 | +tam.infos.duration = window_seconds(1); |
| 488 | +tam.infos.durationinfo = 'duration in seconds'; |
455 | 489 |
|
456 | 490 | tam.timing = model.timing; |
457 | 491 |
|
|
0 commit comments