-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathpop_firpm.m
More file actions
202 lines (182 loc) · 7.71 KB
/
pop_firpm.m
File metadata and controls
202 lines (182 loc) · 7.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
% pop_firpm() - Filter data using Parks-McClellan FIR filter
%
% Usage:
% >> [EEG, com, b] = pop_firpm(EEG); % pop-up window mode
% >> [EEG, com, b] = pop_firpm(EEG, 'key1', value1, 'key2', ...
% value2, 'keyn', valuen);
%
% Inputs:
% EEG - EEGLAB EEG structure
% 'fcutoff' - vector or scalar of cutoff frequency/ies (~-6 dB; Hz)
% 'ftrans' - scalar transition band width
% 'ftype' - char array filter type. 'bandpass', 'highpass',
% 'lowpass', or 'bandstop'
% 'forder' - scalar filter order. Mandatory even
%
% Optional inputs:
% 'wtpass' - scalar passband weight
% 'wtstop' - scalar stopband weight
%
% Outputs:
% EEG - filtered EEGLAB EEG structure
% com - history string
% b - filter coefficients
%
% Note:
% Requires the signal processing toolbox.
%
% Author: Andreas Widmann, University of Leipzig, 2005
%
% See also:
% firfilt, pop_firpmord, plotfresp, firpm, firpmord
%123456789012345678901234567890123456789012345678901234567890123456789012
% Copyright (C) 2005 Andreas Widmann, University of Leipzig, widmann@uni-leipzig.de
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
function [EEG, com, b] = pop_firpm(EEG, varargin)
if ~(exist('firpm', 'file') == 2 || exist('firpm', 'file') == 6)
error('Requires the signal processing toolbox.');
end
com = '';
if nargin < 1
help pop_firpm;
return;
end
if isempty(EEG.data)
error('Cannot process empty dataset');
end
if nargin < 2
drawnow;
ftypes = {'bandpass' 'highpass' 'lowpass' 'bandstop'};
uigeom = {[1 0.75 0.75] [1 0.75 0.75] [1 0.75 0.75] 1 [1 0.75 0.75] [1 0.75 0.75] [1 0.75 0.75] 1 [1 0.75 0.75]};
uilist = {{'Style' 'text' 'String' 'Cutoff frequency(ies) [hp lp] (~-6 dB; Hz):'} ...
{'Style' 'edit' 'String' '' 'Tag' 'fcutoffedit'} {} ...
{'Style' 'text' 'String' 'Transition band width:'} ...
{'Style' 'edit' 'String' '' 'Tag' 'ftransedit'} {} ...
{'Style' 'text' 'String' 'Filter type:'} ...
{'Style' 'popupmenu' 'String' ftypes 'Tag' 'ftypepop'} {} ...
{} ...
{'Style' 'text' 'String' 'Passband weight:'} ...
{'Style' 'edit' 'String' '' 'Tag' 'wtpassedit'} {} ...
{'Style' 'text' 'String' 'Stopband weight:'} ...
{'Style' 'edit' 'String' '' 'Tag' 'wtstopedit'} {} ...
{'Style' 'text' 'String' 'Filter order (mandatory even):'} ...
{'Style' 'edit' 'String' '' 'Tag' 'forderedit'} ...
{'Style' 'pushbutton' 'String' 'Estimate' 'Tag' 'orderpush' 'Callback' {@comcb, ftypes, EEG.srate}} ...
{} ...
{} {} {'Style' 'pushbutton' 'String', 'Plot filter responses' 'Tag' 'plotpush' 'Callback' {@comcb, ftypes, EEG.srate}}};
result = inputgui(uigeom, uilist, 'pophelp(''pop_firpm'')', 'Filter the data -- pop_firpm()');
if isempty(result), return; end
args = {};
if ~isempty(result{1})
args = [args {'fcutoff'} {str2num(result{1})}];
end
if ~isempty(result{2})
args = [args {'ftrans'} {str2double(result{2})}];
end
args = [args {'ftype'} ftypes(result{3})];
if ~isempty(result{4})
args = [args {'wtpass'} {str2double(result{4})}];
end
if ~isempty(result{5})
args = [args {'wtstop'} {str2double(result{5})}];
end
if ~isempty(result{6})
args = [args {'forder'} {str2double(result{6})}];
end
else
args = varargin;
end
% Convert args to structure
args = struct(args{:});
c = parseargs(args, EEG.srate);
if ~isfield(args, 'forder') || isempty(args.forder)
error('Not enough input arguments');
end
b = firpm(args.forder, c{:});
% Filter
disp('pop_firpm() - filtering the data');
EEG = firfilt(EEG, b);
% History string
com = sprintf('%s = pop_firpm(%s', inputname(1), inputname(1));
for c = fieldnames(args)'
if ischar(args.(c{:}))
com = [com sprintf(', ''%s'', ''%s''', c{:}, args.(c{:}))];
else
com = [com sprintf(', ''%s'', %s', c{:}, mat2str(args.(c{:})))];
end
end
com = [com ');'];
% Convert structure args to cell array firpm parameters
function c = parseargs(args, srate)
if ~isfield(args, 'fcutoff') || ~isfield(args, 'ftype') || ~isfield(args, 'ftrans') || isempty(args.fcutoff) || isempty(args.ftype) || isempty(args.ftrans)
error('Not enough input arguments.');
end
% Cutoff frequencies
args.fcutoff = [args.fcutoff - args.ftrans / 2 args.fcutoff + args.ftrans / 2];
args.fcutoff = sort(args.fcutoff / (srate / 2)); % Sorting and normalization
if any(args.fcutoff < 0)
error('Cutoff frequencies - transition band width / 2 must not be < DC');
elseif any(args.fcutoff > 1)
error('Cutoff frequencies + transition band width / 2 must not be > Nyquist');
end
c = {[0 args.fcutoff 1]};
% Filter type
switch args.ftype
case 'bandpass'
c = [c {[0 0 1 1 0 0]}];
case 'bandstop'
c = [c {[1 1 0 0 1 1]}];
case 'highpass'
c = [c {[0 0 1 1]}];
case 'lowpass'
c = [c {[1 1 0 0]}];
end
%Filter weights
if all(isfield(args, {'wtpass', 'wtstop'})) && ~isempty(args.wtpass) && ~isempty(args.wtstop)
w = [args.wtstop args.wtpass];
c{3} = w(c{2}(1:2:end) + 1);
end
% Callback
function comcb(obj, evt, ftypes, srate)
args.fcutoff = str2num(get(findobj(gcbf, 'Tag', 'fcutoffedit'), 'String'));
args.ftype = ftypes{get(findobj(gcbf, 'Tag', 'ftypepop'), 'Value')};
args.ftrans = str2double(get(findobj(gcbf, 'Tag', 'ftransedit'), 'String'));
args.wtpass = str2double(get(findobj(gcbf, 'Tag', 'wtpassedit'), 'String'));
args.wtstop = str2double(get(findobj(gcbf, 'Tag', 'wtstopedit'), 'String'));
c = parseargs(args, srate);
switch get(obj, 'Tag')
case 'orderpush'
[args.forder, args.wtpass, args.wtstop] = pop_firpmord(c{1}(2:end - 1), c{2}(1:2:end));
if ~isempty(args.forder) || ~isempty(args.wtpass) || ~isempty(args.wtstop)
set(findobj(gcbf, 'Tag', 'forderedit'), 'String', ceil(args.forder / 2) * 2);
set(findobj(gcbf, 'Tag', 'wtpassedit'), 'String', args.wtpass);
set(findobj(gcbf, 'Tag', 'wtstopedit'), 'String', args.wtstop);
end
case 'plotpush'
args.forder = str2double(get(findobj(gcbf, 'Tag', 'forderedit'), 'String'));
if isempty(args.forder)
error('Not enough input arguments');
end
b = firpm(args.forder, c{:});
H = findobj('Tag', 'plotfiltresp', 'Type', 'figure');
if ~isempty(H)
figure(H);
else
H = figure;
set(H, 'color', [.93 .96 1], 'Tag', 'plotfiltresp');
end
plotfresp(b, 1, [], srate, 'onepass-zerophase');
end