Back to the main page.
Bug 2364 - If first channel is filled with NaNs complete output of ft_freqanalysis is NaN
Status | CLOSED FIXED |
Reported | 2013-11-05 18:54:00 +0100 |
Modified | 2015-02-11 10:40:47 +0100 |
Product: | FieldTrip |
Component: | specest |
Version: | unspecified |
Hardware: | All |
Operating System: | Linux |
Importance: | P3 normal |
Assigned to: | Robert Oostenveld |
URL: | |
Tags: | |
Depends on: | |
Blocks: | |
See also: |
Joscha Schmiedt - 2013-11-05 18:54:47 +0100
If the first channel of a dataset has been filled with NaNs, e.g., as a result of ft_rejectvisual with cfg.keepchannel = 'nan', the output of ft_freqanalysis is NaN for all channels. This does not happen for channels 2:end. Code for reproducing: nTrials = 20; data = []; data.fsample = 256; data.trial = arrayfun(@(x) rand(10, 512), 1:nTrials, 'UniformOutput', false); data.time = repmat({(0:length(data.trial{1})-1)/data.fsample}, [1, nTrials]); data.label = cellfun(@num2str, num2cell(1:10), 'UniformOutput', false); for iTrial = 1:nTrials data.trial{iTrial}(1,:) = nan; end cfg = []; cfg.method = 'wavelet'; cfg.width = 2; cfg.foilim = [10 50]; cfg.toi = 0:0.01:2; tf = ft_freqanalysis(cfg, data); fprintf('number of non-nans for wavelet method: %i\n', sum(~isnan(tf.powspctrm(:)))) cfg = []; cfg.method = 'mtmconvol'; cfg.taper = 'hanning'; cfg.foi = 10:50; cfg.t_ftimwin = 2./cfg.foi; cfg.toi = 0:0.01:2; tf = ft_freqanalysis(cfg, data); sum(~isnan(tf.powspctrm(:))) fprintf('number of non-nans for mtmconvol method: %i\n', sum(~isnan(tf.powspctrm(:))))
Joscha Schmiedt - 2013-11-05 19:18:47 +0100
It seems to be enough if one value in the first channel is NaN. This has been tested with ft_freqanalysis 8625 2013-10-23 09:50:42Z roevdmei
Robert Oostenveld - 2014-10-07 12:36:27 +0200
(In reply to Joscha Schmiedt from comment #1) Given the increased support in artefact handling allowing the channel value to be represented as nan in case the channel is bad, this is bad. Looking at the low-level code, these seem to be OK fat = squeeze(ft_specest_mtmfft(data.trial{1}, data.time{1}, 'taper', 'hanning')) fat = squeeze(ft_specest_mtmconvol(data.trial{1}, data.time{1}, 'taper', 'hanning', 'timwin', 0.5))
Robert Oostenveld - 2014-10-07 12:51:13 +0200
the problem is with line 598 in ft_freqanalysis, where acttboi = squeeze(~isnan(spectrum(1,1,foiind(ifoi),:))); it looks at the first channel to (I guess) determine time bins of interest.
Robert Oostenveld - 2014-10-07 13:00:58 +0200
I changed the code, rather than looking at the first channel, it now uses all(isnan(..)) mac011> svn commit test/test_bug2364.m ft_freqanalysis.m Sending ft_freqanalysis.m Adding test/test_bug2364.m Transmitting file data .. Committed revision 9883.
Jim Herring - 2014-11-10 13:29:17 +0100
As discussed with Robert during lunch, this fix now results in single-channel data (e.g. virtual channel data) to result in nans as reported by various users.
Robert Oostenveld - 2014-11-10 14:30:52 +0100
data1 = []; data1.label = {'1'}; data1.time = {(1:1000)/1000} data1.trial = {randn(1,1000)} data2 = []; data2.label = {'1', '2'}; data2.time = {(1:1000)/1000} data2.trial = {randn(2,1000)} data2.trial{1}(1,:) = data1.trial{1}; cfg = []; cfg.method = 'wavelet'; cfg.width = 2; cfg.foilim = [10 50]; cfg.toi = 0:0.01:2 tf1 = ft_freqanalysis(cfg, data1); tf2 = ft_freqanalysis(cfg, data2); assert(isequal(tf1.powspctrm(1,:,:), tf2.powspctrm(1,:,:))) confirms the problem.
Robert Oostenveld - 2014-11-10 14:45:50 +0100
(In reply to Robert Oostenveld from comment #6) in ft_freqanalysis there is at line 602 now this acttboi = ~all(isnan(squeeze(spectrum(1,:,foiind(ifoi),:))), 1); which prior to change 9883 used to be acttboi = squeeze(~isnan(spectrum(1,1,foiind(ifoi),:))); In the example I just gave, they are different. However, I don't understand what the code is doing (yet).
Robert Oostenveld - 2014-11-10 14:48:49 +0100
... but it is clear that the problem is in the squeeze K>> size(spectrum(1,:,foiind(ifoi),:)) ans = 1 1 1 101 K>> size(squeeze(spectrum(1,:,foiind(ifoi),:))) ans = 101 1 Here with nchan>1 the first dimension would map onto channels after the squeeze. I have to go now, will pick this up later.
Jim Herring - 2014-11-10 15:11:49 +0100
Perhaps something like the following is more appropriate: temp = size(spectrum(1,:,foiind(ifoi),:)); spectrum = reshape(spectrum(1,:,foiind(ifoi),:),temp(2),temp(4)); as we wish to squeeze out the first and third dimension, while keeping the 2nd and 4th.
Jim Herring - 2014-11-12 16:05:48 +0100
The following works but there might be a more elegant solution: temp = size(spectrum(1,:,foiind(ifoi),:)); acttboi = ~all(isnan(reshape(spectrum(1,:,foiind(ifoi),:),temp(2),temp(4))), 1); nacttboi = sum(acttboi);
Robert Oostenveld - 2014-11-13 13:32:44 +0100
this fixes the regression error, keeping the fix for the first issue intact. mac011> svn commit specest/ft_specest_wavelet.m ft_freqanalysis.m test/ Sending ft_freqanalysis.m Sending specest/ft_specest_wavelet.m Sending test/test_bug2364.m Transmitting file data ... Committed revision 9963.
Robert Oostenveld - 2014-12-10 18:00:14 +0100
*** Bug 2757 has been marked as a duplicate of this bug. ***
Robert Oostenveld - 2014-12-10 18:01:17 +0100
I just noticed single channel mtmfft to fail. Fs = 1000; time = (1:Fs)/Fs; signal = randn(size(time)); data = []; data.time{1} = time; data.trial{1} = signal; data.label = 'A1'; cfg = []; cfg.taper = 'boxcar'; cfg.method = 'mtmfft'; cfg.foilim = [0 500]; freq = ft_freqanalysis(cfg, data); Error using reshape To RESHAPE the number of elements must not change. Error in ft_freqanalysis (line 649) powspctrm(:,ifoi,acttboi) = powspctrm(:,ifoi,acttboi) + (reshape(mean(powdum,1),[nchan 1 nacttboi]) ./ ntrials);
Robert Oostenveld - 2014-12-10 18:04:36 +0100
sorry, my bad. It turned out that the error was due to data.label = 'A1'; rather than data.label = {'A1'}; causing a channel count mismatch.