Concrete scenario causing the crash:
- An EEG dataset has an
EEG.srate == 256
- and the script uses this window:
cfgTimeexpand.timelimits = [-0.1, 0.7];
- Matlab 2023b (irrelevant)
uf_timeexpandDesignmat() then crashes for many participants when function sparse() is called (line 173 :
Xdc = sparse( round(indrow_all(~removeIdx)), round(indcol_all(~removeIdx)), val_all(~removeIdx), dimFullX(1), dimFullX(2) );
with this error:
Error using sparse
Index into matrix must be positive.
Apparent cause of problem
Row indices for the sparse matrix are computed here:
shiftvec = (1:cfg.windowlength) + cfg.timelimits(1) * EEG.srate - 1;
tmp = bsxfun(@plus, rowix, shiftvec);
indrow_all = tmp(:)';
For EEG.srate = 256 and cfg.timelimits(1) = -0.1,
cfg.timelimits(1) * EEG.srate should be -25.6, but due to floating-point precision becomes values such as:
-25.599999999999998
This generates fractional indices like: 0.23, 0.41, ...
For certain integer event latencies rowix, rowix + (-25.599999999999998) lands in (0, 1), e.g. 26 + (-25.6) ≈ 0.4.
These values are larger than zero and therefore (unfortunately) survive this exclusion:
removeIdx = indrow_all > dimFullX(1) | indrow_all <= 0;
...however, they later become zeros via round(), causing the error (non-positive index).
Proposed fix:
Replace
shiftvec = [1:cfg.windowlength] + cfg.timelimits(1)*EEG.srate - 1;
with
shiftvec = (1:cfg.windowlength) + cfg.reallims(1) - 1;
because cfg.reallims(1) is already rounded and was already created as:
cfg.reallims(1) = round(cfg.timelimits(1) * EEG.srate);
@behinger: Wanna take a second look at this to confirm?
Concrete scenario causing the crash:
EEG.srate == 256cfgTimeexpand.timelimits = [-0.1, 0.7];uf_timeexpandDesignmat()then crashes for many participants when functionsparse()is called (line 173 :Xdc = sparse( round(indrow_all(~removeIdx)), round(indcol_all(~removeIdx)), val_all(~removeIdx), dimFullX(1), dimFullX(2) );with this error:
Apparent cause of problem
Row indices for the sparse matrix are computed here:
For EEG.srate = 256 and cfg.timelimits(1) = -0.1,
cfg.timelimits(1) * EEG.srate should be -25.6, but due to floating-point precision becomes values such as:
-25.599999999999998
This generates fractional indices like: 0.23, 0.41, ...
For certain integer event latencies rowix, rowix + (-25.599999999999998) lands in (0, 1), e.g. 26 + (-25.6) ≈ 0.4.
These values are larger than zero and therefore (unfortunately) survive this exclusion:
removeIdx = indrow_all > dimFullX(1) | indrow_all <= 0;...however, they later become zeros via
round(), causing the error (non-positive index).Proposed fix:
Replace
shiftvec = [1:cfg.windowlength] + cfg.timelimits(1)*EEG.srate - 1;with
shiftvec = (1:cfg.windowlength) + cfg.reallims(1) - 1;because cfg.reallims(1) is already rounded and was already created as:
cfg.reallims(1) = round(cfg.timelimits(1) * EEG.srate);@behinger: Wanna take a second look at this to confirm?