% POP_EEGFILT - interactively filter EEG dataset data using EEGFILT
%
% Usage:
% >> EEGOUT = pop_eegfilt( EEG, locutoff, hicutoff, filtorder);
%
% Graphical interface:
% "Lower edge ..." - [edit box] Lower edge of the frequency pass band (Hz)
% Same as the 'locutoff' command line input.
% "Higher edge ..." - [edit box] Higher edge of the frequency pass band (Hz)
% Same as the 'hicutoff' command line input.
% "Notch filter" - [edit box] provide the notch range, i.e. [45 55]
% for 50 Hz). This option overwrites the low and high edge limits
% given above. Set the 'locutoff' and 'hicutoff' values to the
% values entered as parameters, and set 'revfilt to 1, to swap
% from bandpass to notch filtering.
% "Filter length" - [edit box] Filter length in point (default: see
% >> help eegfilt). Same as 'filtorder' optional input.
%
% Inputs:
% EEG - input dataset
% locutoff - lower edge of the frequency pass band (Hz) {0 -> lowpass}
% hicutoff - higher edge of the frequency pass band (Hz) {0 -> highpass}
% filtorder - length of the filter in points {default 3*fix(srate/locutoff)}
% revfilt - [0|1] Reverse filter polarity (from bandpass to notch filter).
% Default is 0 (bandpass).
% usefft - [0|1] 1 uses FFT filtering instead of FIR. Default is 0.
% plotfreqz - [0|1] plot frequency response of filter. Default is 0.
% firtype - ['firls'|'fir1'] filter design method, default is 'firls'
% from the command line
% causal - [0|1] 1 uses causal filtering. Default is 0.
%
% Outputs:
% EEGOUT - output dataset
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: EEGFILT, EEGFILTFFT, EEGLAB
% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
% 01-25-02 reformated help & license -ad
function [EEG, com] = pop_eegfilt( EEG, locutoff, hicutoff, filtorder, revfilt, usefft, plotfreqz, firtype, causal)
com = '';
if nargin < 1
help pop_eegfilt;
return;
end
if isempty(EEG(1).data)
disp('Pop_eegfilt() error: cannot filter an empty dataset'); return;
end
% warning
% -------
if exist('filtfilt') ~= 2
disp('Warning: cannot find the signal processing toolbox');
disp(' a simple fft/inverse fft filter will be used');
usefft = 1;
end
if nargin < 2
% which set to save
% -----------------
uilist = { ...
{ 'style' 'text' 'string' 'Lower edge of the frequency pass band (Hz)' } ...
{ 'style' 'edit' 'string' '' } ...
{ 'style' 'text' 'string' 'Higher edge of the frequency pass band (Hz)' } ...
{ 'style' 'edit' 'string' '' } ...
{ 'style' 'text' 'string' 'FIR Filter order (default is automatic)' } ...
{ 'style' 'edit' 'string' '' } ...
{ 'style' 'checkbox' 'string' 'Notch filter the data instead of pass band' } ...
{ 'style' 'checkbox' 'string' 'Use (sharper) FFT linear filter instead of FIR filtering' 'value' 0 } ...
{ 'style' 'text' 'string' '(Use the option above if you do not have the Signal Processing Toolbox)' } ...
{ 'style' 'checkbox' 'string' 'Use causal filter (useful when performing causal analysis)' 'value' 0} ...
{ 'style' 'checkbox' 'string' 'Plot the filter frequency response' 'value' 0} ...
{ 'style' 'checkbox' 'string' 'Use fir1 (check, recommended) or firls (uncheck, legacy)' 'value' 1}};
geometry = { [3 1] [3 1] [3 1] 1 1 1 1 1 1 };
result = inputgui( 'geometry', geometry, 'uilist', uilist, 'title', 'Filter the data -- pop_eegfilt()', ...
'helpcom', 'pophelp(''pop_eegfilt'')');
if isempty(result), return; end
if isempty(result{1}), result{1} = '0'; end
if isempty(result{2}), result{2} = '0'; end
locutoff = eval( result{1} );
hicutoff = eval( result{2} );
if isempty( result{3} )
filtorder = [];
else filtorder = eval( result{3} );
end
revfilt = 0;
if result{4}
revfilt = 1;
if locutoff == 0 || hicutoff == 0
error('Need both lower and higher edge for notch filter');
end
end
if result{5}
usefft = 1;
else usefft = 0;
end
if result{6}
causal = 1;
else causal = 0;
end
plotfreqz = result{7};
if locutoff == 0 && hicutoff == 0
return;
end
if result{8}
firtype = 'fir1';
else
firtype = 'firls';
end
else
if nargin < 3
hicutoff = 0;
end
if nargin < 4
filtorder = [];
end
if nargin < 5
revfilt = 0;
end
if nargin < 6
usefft = 0;
end
if nargin < 7
plotfreqz = 0;
end
if nargin < 8
firtype = 'firls';
end
if nargin < 8
causal = 0;
end
end
if locutoff && hicutoff
disp('WARNING: BANDPASS FILTERS SOMETIMES DO NOT WORK (MATLAB BUG)')
disp('WARNING: PLOT SPECTRUM AFTER FILTERING TO ASSESS FILTER EFFICIENCY')
disp('WARNING: IF FILTER FAILS, LOWPASS DATA THEN HIGHPASS DATA')
end
% process multiple datasets
% -------------------------
if length(EEG) > 1
[ EEG, com ] = eeg_eval( 'pop_eegfilt', EEG, 'warning', 'on', 'params', ...
{ locutoff, hicutoff, filtorder, revfilt, usefft, plotfreqz, firtype, causal} );
return;
end
options = { EEG.srate, locutoff, hicutoff, 0 };
if ~isempty( filtorder )
options = { options{:} filtorder };
else
options = { options{:} 0 };
end
options = {options{:} revfilt firtype causal};
eeglab_options;
if EEG.trials == 1
if ~isempty(EEG.event) && isfield(EEG.event, 'type')
tmpevent = EEG.event;
boundaries = eeg_findboundaries(tmpevent);
if isempty(boundaries)
if ~usefft
[EEG.data, b] = eegfilt( EEG.data, options{:});
else
EEG.data = eegfiltfft( EEG.data, options{1:6}); % 7/30/2014 Ramon: {:} to {1:6};
end
else
options{4} = 0;
disp('Pop_eegfilt:finding continuous data boundaries');
tmplat = [ tmpevent.latency ];
boundaries = tmplat(boundaries);
boundaries = [0 floor(boundaries-0.49) EEG.pnts];
try
warning('off','MATLAB:divideByZero');
catch, end
for n=1:length(boundaries)-1
if boundaries(n)+1 < boundaries(n+1)
try
fprintf('Processing continuous data (%d:%d)\n',boundaries(n),boundaries(n+1));
if ~usefft
[EEG.data(:,boundaries(n)+1:boundaries(n+1)), b] = ...
eegfilt(EEG.data(:,boundaries(n)+1:boundaries(n+1)), options{:});
else
EEG.data(:,boundaries(n)+1:boundaries(n+1)) = ...
eegfiltfft(EEG.data(:,boundaries(n)+1:boundaries(n+1)), options{1:6}); % 7/30/2014 Ramon: {:} to {1:6};
end
catch
fprintf('\nFilter error: continuous data portion too narrow (DC removed if highpass only)\n');
if locutoff ~= 0 && hicutoff == 0
tmprange = [boundaries(n)+1:boundaries(n+1)];
EEG.data(:,tmprange) = ...
EEG.data(:,tmprange) - repmat(mean(EEG.data(:,tmprange),2), [1 length(tmprange)]);
end
end
end
end
try
warning('on', 'MATLAB:divideByZero');
catch, end
end
else
if ~usefft
[EEG.data, b] = eegfilt( EEG.data, options{:});
else
EEG.data = eegfiltfft( EEG.data, options{1:6}); % 7/30/2014 Ramon: {:} to {1:6};
end
end
else
EEG.data = reshape(EEG.data, EEG.nbchan, EEG.pnts*EEG.trials);
options{4} = EEG.pnts;
if ~usefft
[EEG.data, b] = eegfilt( EEG.data, options{:});
else
EEG.data = eegfiltfft( EEG.data, options{1:6}); % 7/30/2014 Ramon: {:} to {1:6};
end
% Note: reshape does not reserve new memory while EEG.data(:,:) does
end
EEG.icaact = [];
if ~usefft && plotfreqz && exist('b') == 1
freqz(b, 1, [], EEG.srate);
end
com = sprintf( 'EEG = pop_eegfilt( EEG, %s, %s, [%s], [%s], %s, %s, ''%s'', %d);',...
num2str( locutoff), num2str( hicutoff), num2str( filtorder ), num2str( revfilt ), num2str(usefft), num2str(plotfreqz), firtype, causal);
return