function [psdmed, psdvar, psdkrt] = eeg_rpsd(EEG, nfreqs, pct_data) % clean input cutoff freq nyquist = floor(EEG.srate / 2); if ~exist('nfreqs', 'var') || isempty(nfreqs) nfreqs = nyquist; elseif nfreqs > nyquist nfreqs = nyquist; end if ~exist('pct_data', 'var') || isempty(pct_data) pct_data = 100; end % setup constants ncomp = size(EEG.icaweights, 1); n_points = min(EEG.pnts, EEG.srate); window = hamming(n_points)'; cutoff = floor(EEG.pnts / n_points) * n_points; index = bsxfun(@plus, ceil(0:n_points / 2:cutoff - n_points), (1:n_points)'); rng(0) n_seg = size(index, 2) * EEG.trials; subset = randperm(n_seg, ceil(n_seg * pct_data / 100)); % need to improve this rng('shuffle') try %% slightly faster but high memory use % calculate windowed spectrums temp = reshape(EEG.icaact(:, index, :), [ncomp size(index) .* [1 EEG.trials]]); temp = bsxfun(@times, temp(:, :, subset), window); temp = fft(temp, n_points, 2); temp = abs(temp).^2; temp = temp(:, 2:nfreqs + 1, :) * 2 / (EEG.srate*sum(window.^2)); if nfreqs == nyquist temp(:, end, :) = temp(:, end, :) / 2; end % calculate outputs psdmed = db(median(temp, 3)); psdvar = db(var(temp, [], 3), 'power'); psdkrt = db(kurtosis(temp, [], 3)/4); catch %% lower memory but slightly slower psdmed = zeros(ncomp, nfreqs); psdvar = zeros(ncomp, nfreqs); psdkrt = zeros(ncomp, nfreqs); for it = 1:ncomp % calculate windowed spectrums temp = reshape(EEG.icaact(it, index, :), [1 size(index) .* [1 EEG.trials]]); temp = bsxfun(@times, temp(:, :, subset), window); temp = fft(temp, n_points, 2); temp = temp .* conj(temp); temp = temp(:, 2:nfreqs + 1, :) * 2 / (EEG.srate*sum(window.^2)); if nfreqs == nyquist temp(:, end, :) = temp(:, end, :) / 2; end psdmed(it, :) = db(median(temp, 3)); psdvar(it, :) = db(var(temp, [], 3), 'power'); psdkrt(it, :) = db(kurtosis(temp, [], 3)/4); end end end