Mercurial > hg > ltpda
comparison m-toolbox/classes/@ltpda_tf/resp.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
1 % RESP returns the complex response of a transfer function as an Analysis Object. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: RESP returns the complex response of a transfer function as | |
5 % an Analysis Object. | |
6 % | |
7 % CALL: a = resp(obj, f); % compute response for vector f | |
8 % a = resp(obj, f1, f2, nf); % compute response from f1 to f2 in nf | |
9 % steps. | |
10 % a = resp(obj, pl); % compute response from parameter list. | |
11 % a = resp(obj); % compute response | |
12 % | |
13 % <a href="matlab:utils.helper.displayMethodInfo('ltpda_tf', 'resp')">Parameters Description</a> | |
14 % | |
15 % VERSION: $Id: resp.m,v 1.14 2011/04/18 16:50:51 ingo Exp $ | |
16 % | |
17 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
18 | |
19 function varargout = resp(varargin) | |
20 | |
21 %%% Check if this is a call for parameters | |
22 if utils.helper.isinfocall(varargin{:}) | |
23 varargout{1} = getInfo(varargin{3}); | |
24 return | |
25 end | |
26 | |
27 %%% Input objects checks | |
28 if nargin < 1 | |
29 error('### incorrect number of inputs.') | |
30 end | |
31 | |
32 objs = {}; | |
33 rest = {}; | |
34 plin = []; | |
35 invars = {}; | |
36 % Check input shape | |
37 % only one input -> keep shape | |
38 % more than one input -> convert to list. | |
39 classMatch = zeros(nargin, 1); | |
40 for ii = 1:nargin | |
41 if isa(varargin{ii}, 'ltpda_tf') | |
42 classMatch(ii) = 1; | |
43 end | |
44 end | |
45 | |
46 for ii = 1:nargin | |
47 if classMatch(ii) == 1 | |
48 if sum(classMatch) == 1 | |
49 objs = num2cell(varargin{ii}); | |
50 invars = [invars repmat({inputname(ii)}, 1, numel(varargin{ii}))]; | |
51 else | |
52 objs = [objs reshape(num2cell(varargin{ii}), 1, [])]; | |
53 invars = [invars repmat({inputname(ii)}, 1, numel(varargin{ii}))]; | |
54 end | |
55 else | |
56 if isa(varargin{ii}, 'plist') | |
57 plin = [plin varargin{ii}]; | |
58 else | |
59 rest = [rest {varargin{ii}}]; | |
60 end | |
61 end | |
62 end | |
63 | |
64 % Combine the input plists | |
65 plin = combine(plin, plist()); | |
66 | |
67 % Initialize output | |
68 bank = plin.combine(getDefaultPlist('Range')).find('bank'); | |
69 switch lower(bank) | |
70 case 'none' | |
71 bs = ao.initObjectWithSize(size(objs,1), size(objs,2)); | |
72 otherwise | |
73 bs = []; | |
74 end | |
75 | |
76 % Loop over transfer functions | |
77 for pp=1:numel(objs) | |
78 | |
79 % process this transfer function | |
80 obj = objs{pp}; | |
81 % Now look at the model | |
82 name = obj.name; | |
83 | |
84 if (plin.isparam('f')) || ... | |
85 (numel(rest) == 1 && isnumeric(rest{1}) && isvector(rest{1})) || ... | |
86 (numel(rest) == 1 && isa(rest{1}, 'ao') && isa(rest{1}.data, 'fsdata')) || ... | |
87 (numel(rest) == 1 && isa(rest{1}, 'ao') && isa(rest{1}.data, 'xydata')) | |
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
89 %%%%%%%%%% Response with a f vector %%%%%%%%%% | |
90 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
91 %%% r = obj.resp(plist-object('f')) | |
92 %%% r = obj.resp(ao-object(fsdata)) | |
93 %%% r = obj.resp(ao-object(xydata)) | |
94 | |
95 if numel(rest) == 1 | |
96 pl = combine(plist('f', rest{1}), getDefaultPlist('List')); | |
97 else | |
98 pl = combine(plin, getDefaultPlist('List')); | |
99 end | |
100 | |
101 %%% Get f-vector | |
102 f = pl.find('f'); | |
103 | |
104 %%% Get the f-vector from the AO | |
105 if isa(f, 'ao') | |
106 f = f.data.x; | |
107 elseif isnumeric(f) && isvector(f) | |
108 %%% nothing to do | |
109 else | |
110 error('### The f-vector must be a vector or an AO, but it is from the class [%s]', class(f)); | |
111 end | |
112 | |
113 elseif (plin.isparam('f1')) || ... | |
114 (plin.isparam('f2')) || ... | |
115 (numel(rest) == 0) || ... | |
116 (numel(rest) == 2 && isnumeric(rest{1}) && isnumeric(rest{2})) || ... | |
117 (numel(rest) == 3 && isnumeric(rest{1}) && isnumeric(rest{2}) && isnumeric(rest{3})) | |
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
119 %%%%%%%%%% Response with f1, f2 and nf %%%%%%%%%% | |
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
121 %%% r = obj.resp(plist-object('f1', 'f2')) | |
122 %%% r = obj.resp(plist-object('f1')) | |
123 %%% r = obj.resp(plist-object('f2')) | |
124 %%% r = obj.resp() | |
125 %%% r = obj.resp(f1, f2) | |
126 %%% r = obj.resp(f1, f2, nf) | |
127 | |
128 if numel(rest) == 0 && plin.nparams == 0 | |
129 pl = getDefaultPlist('Range'); | |
130 | |
131 elseif numel(rest) == 2 | |
132 pl = combine(plist('f1', rest{1}, 'f2', rest{2}), getDefaultPlist('Range')); | |
133 | |
134 elseif numel(rest) == 3 | |
135 pl = combine(plist('f1', rest{1}, 'f2', rest{2}, 'nf', rest{3}), getDefaultPlist('Range')); | |
136 | |
137 else | |
138 pl = combine(plin, getDefaultPlist('Range')); | |
139 end | |
140 | |
141 f1 = pl.find('f1'); | |
142 f2 = pl.find('f2'); | |
143 nf = pl.find('nf'); | |
144 scale = pl.find('scale'); | |
145 | |
146 % Get the default values if 'f1' or 'f2' are not existing | |
147 if isa(obj, 'miir') || isa(obj, 'mfir') | |
148 % Special case for iir- and fir filters. | |
149 if isempty(f1), f1 = obj.fs/1000; end | |
150 if isempty(f2), f2 = obj.fs/2-1/nf; end | |
151 if isempty(f1), f1 = 0; end | |
152 if isempty(f2), f2 = 0.5; end | |
153 | |
154 else | |
155 if isempty(f1), f1 = getlowerFreq(obj)/10; end | |
156 if isempty(f2), f2 = getupperFreq(obj)*10; end | |
157 end | |
158 | |
159 switch lower(scale) | |
160 case 'lin' | |
161 f = linspace(f1, f2, nf); | |
162 case 'log' | |
163 f = logspace(log10(f1), log10(f2), nf); | |
164 end | |
165 | |
166 else | |
167 error('### Unknown or incorrect number of inputs.'); | |
168 end | |
169 | |
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
171 %%%%%%%%%% deal with rows %%%%%%%%%% | |
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
173 reshape_f = false; | |
174 if size(f,1) > 1 | |
175 f = f.'; | |
176 reshape_f = true; | |
177 end | |
178 | |
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
180 %%%%%%%%%% compute the response %%%%%%%%%% | |
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
182 | |
183 r = respCore(obj, f); | |
184 | |
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
186 %%%%%%%%%% Build output AO %%%%%%%%%% | |
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
188 if reshape_f | |
189 f = f.'; | |
190 r = r.'; | |
191 end | |
192 | |
193 % create new output fsdata | |
194 fsd = fsdata(f, r); | |
195 | |
196 % set yunits = ounits./iunits | |
197 fsd.setXunits('Hz'); | |
198 fsd.setYunits(obj.ounits./obj.iunits); | |
199 | |
200 % set fs, if the object is a discrete filter | |
201 if isa(obj, 'ltpda_filter') | |
202 fsd.setFs(obj.fs); | |
203 end | |
204 | |
205 % make output analysis object | |
206 b = ao(fsd); | |
207 | |
208 switch lower(bank) | |
209 case 'none' | |
210 % Add history | |
211 b.addHistory(getInfo('None'), pl, invars, obj.hist); | |
212 % set name | |
213 if isempty(name) | |
214 b.setName(sprintf('resp(%s)', invars{pp})); | |
215 else | |
216 b.setName(sprintf('resp(%s)', name)); | |
217 end | |
218 % Add to outputs | |
219 bs(pp) = b; | |
220 | |
221 case 'serial' | |
222 if isempty(bs) | |
223 bs = b; | |
224 oname = obj.name; | |
225 else | |
226 bs = bs .* b; | |
227 oname = [oname '.*' obj.name]; | |
228 end | |
229 | |
230 case 'parallel' | |
231 if isempty(bs) | |
232 bs = b; | |
233 oname = obj.name; | |
234 else | |
235 bs = bs + b; | |
236 oname = [oname '+' obj.name]; | |
237 end | |
238 otherwise | |
239 error('Unknown option for parameter ''bank'': %s', bank); | |
240 end | |
241 | |
242 end | |
243 | |
244 if strcmpi(bank, 'parallel') || strcmpi(bank, 'serial') | |
245 inhists = []; | |
246 for ii = 1:numel(objs) | |
247 inhists = [inhists objs{ii}.hist]; | |
248 end | |
249 % Add history | |
250 bs.addHistory(getInfo('None'), pl, [], inhists); | |
251 % set name | |
252 bs.setName(sprintf('resp(%s)', oname)); | |
253 end | |
254 | |
255 % Outputs | |
256 if nargout == 0 | |
257 iplot(bs) | |
258 elseif nargout == numel(bs) | |
259 % List of outputs | |
260 for ii = 1:numel(bs) | |
261 varargout{ii} = bs(ii); | |
262 end | |
263 else | |
264 % Single output | |
265 varargout{1} = bs; | |
266 end | |
267 | |
268 end | |
269 | |
270 | |
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
272 % Local Functions % | |
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
274 | |
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
276 % | |
277 % FUNCTION: getInfo | |
278 % | |
279 % DESCRIPTION: Get Info Object | |
280 % | |
281 % HISTORY: 11-07-07 M Hewitson | |
282 % Creation. | |
283 % | |
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
285 | |
286 function ii = getInfo(varargin) | |
287 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
288 sets = {}; | |
289 pls = []; | |
290 elseif nargin == 1&& ~isempty(varargin{1}) && ischar(varargin{1}) | |
291 sets{1} = varargin{1}; | |
292 pls = getDefaultPlist(sets{1}); | |
293 else | |
294 sets = {'List', 'Range'}; | |
295 pls = []; | |
296 for kk=1:numel(sets) | |
297 pls = [pls getDefaultPlist(sets{kk})]; | |
298 end | |
299 end | |
300 % Build info object | |
301 ii = minfo(mfilename, 'ltpda_tf', 'ltpda', utils.const.categories.sigproc, '$Id: resp.m,v 1.14 2011/04/18 16:50:51 ingo Exp $', sets, pls); | |
302 ii.setModifier(false); | |
303 ii.setArgsmin(1); | |
304 end | |
305 | |
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
307 % | |
308 % FUNCTION: getDefaultPlist | |
309 % | |
310 % DESCRIPTION: Get Default Plist | |
311 % | |
312 % HISTORY: 11-07-07 M Hewitson | |
313 % Creation. | |
314 % | |
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
316 | |
317 function plout = getDefaultPlist(set) | |
318 persistent pl; | |
319 persistent lastset; | |
320 if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set) | |
321 pl = buildplist(set); | |
322 lastset = set; | |
323 end | |
324 plout = pl; | |
325 end | |
326 | |
327 function plo = buildplist(set) | |
328 switch lower(set) | |
329 case 'list' | |
330 | |
331 plo = plist(); | |
332 | |
333 p = param({'f',['A vector of frequencies to evaluate at or an AO \n',... | |
334 'whereby the x-axis is taken for the frequency values.']}, paramValue.EMPTY_DOUBLE); | |
335 plo.append(p); | |
336 | |
337 case 'range' | |
338 plo = plist(); | |
339 | |
340 p = param({'f1','Start frequency.'}, paramValue.EMPTY_DOUBLE); | |
341 plo.append(p); | |
342 | |
343 p = param({'f2','Stop frequency.'}, paramValue.EMPTY_DOUBLE); | |
344 plo.append(p); | |
345 | |
346 p = param({'nf','Number of evaluation frequencies.'}, paramValue.DOUBLE_VALUE(1000)); | |
347 plo.append(p); | |
348 | |
349 p = param({'scale',['Spacing of frequencies:<ul>', ... | |
350 '<li>''lin'' - Linear scale.</li>', ... | |
351 '<li>''log'' - Logarithmic scale.</li></ul>']}, {2, {'lin', 'log'} paramValue.SINGLE}); | |
352 plo.append(p); | |
353 | |
354 otherwise | |
355 error('### Unknown set [%s]', set); | |
356 end | |
357 | |
358 p = param({'bank',['How to handle a vector of input filters<br/>(only iir and fir filters):<ul>',... | |
359 '<li>''None'' - process each filter individually.</li>',... | |
360 '<li>''Serial'' - return the response of a serial filter bank.</li>',... | |
361 '<li>''Parallel'' - return the response of a parallel filter bank.</li></ul>']}, {1, {'none', 'serial', 'parallel'}, paramValue.SINGLE}); | |
362 plo.append(p); | |
363 | |
364 end | |
365 |