Mercurial > hg > ltpda
comparison m-toolbox/classes/@ssm/cpsdForIndependentInputs.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 % CPSDFORINDEPENDENTINPUTS computes the output theoretical CPSD shape with given inputs. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: cpsdForIndependentInputs computes the output theoretical | |
5 % CPSD or PSD shape for given input shapes. | |
6 % It returns summed and individual contributions and takes | |
7 % input vectors of objects (instead of square matrices) | |
8 % | |
9 % CALL: [mat_outSum, mat_out] = PSD(sys, pl) | |
10 % | |
11 % INPUTS: | |
12 % sys - (array of) ssm object | |
13 % | |
14 % OUTPUTS: | |
15 % mat_outSum - contains specified returned aos, noise is | |
16 % summed over all the specified input noises | |
17 % mat_out - contains specified returned aos | |
18 % | |
19 % <a href="matlab:utils.helper.displayMethodInfo('ssm', 'cpsdForIndependentInputs')">Parameters Description</a> | |
20 % | |
21 % VERSION: $Id: cpsdForIndependentInputs.m,v 1.2 2011/05/23 14:18:20 adrien Exp $ | |
22 % | |
23 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
24 | |
25 function varargout = cpsdForIndependentInputs(varargin) | |
26 | |
27 %% starting initial checks | |
28 | |
29 % use the caller is method flag | |
30 callerIsMethod = utils.helper.callerIsMethod; | |
31 | |
32 % Check if this is a call for parameters | |
33 if utils.helper.isinfocall(varargin{:}) | |
34 varargout{1} = getInfo(varargin{3}); | |
35 return | |
36 end | |
37 | |
38 utils.helper.msg(utils.const.msg.MNAME, ['running ', mfilename]); | |
39 | |
40 % Collect input variable names | |
41 in_names = cell(size(varargin)); | |
42 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
43 | |
44 % Collect all SSMs and plists | |
45 [sys, ssm_invars, rest] = utils.helper.collect_objects(varargin(:), 'ssm', in_names); | |
46 [pl, invars2, rest] = utils.helper.collect_objects(rest(:), 'plist'); | |
47 if ~isempty(rest) | |
48 pl = combine(pl, plist(rest{:})); | |
49 end | |
50 pl = combine(pl, getDefaultPlist()); | |
51 | |
52 %%% Internal call: Only one object + don't look for a plist | |
53 internal = strcmp(varargin{end}, 'internal'); | |
54 | |
55 %% begin function body | |
56 | |
57 %% retrieve system infos | |
58 | |
59 if numel(sys)~=1 | |
60 error('noisespectrum needs exactly one ssm as an input') | |
61 end | |
62 if ~sys.isnumerical | |
63 error(['error because system ',sys.name,' is not numerical']); | |
64 end | |
65 if ~sys.isStable | |
66 error('input ssm is not stable!') | |
67 end | |
68 if sys.timestep==0 | |
69 timestep = 1; | |
70 else | |
71 timestep = sys.timestep; | |
72 end | |
73 if ~internal | |
74 inhist = sys.hist; | |
75 end | |
76 | |
77 %% modifying system's ordering | |
78 if find(pl, 'reorganize') | |
79 sys = reorganize(sys, pl, 'set', 'for cpsdForIndependentInputs', 'internal', 'internal'); | |
80 end | |
81 | |
82 %% collecting functions i/o data | |
83 aos_in = find(pl, 'aos'); | |
84 PZ_in = find(pl, 'PZmodels'); | |
85 cov_in = find(pl, 'variance'); | |
86 cpsd_in = find(pl, 'PSD'); | |
87 | |
88 noise_mat = [... | |
89 reshape(cov_in, [numel(cov_in),1]) ; ... | |
90 reshape(cpsd_in, [numel(cpsd_in),1]) / (timestep*2)]; | |
91 if sum(noise_mat<0) > 0 | |
92 error('input PSD is not positive!') | |
93 end | |
94 | |
95 %% getting system's i/o sizes | |
96 inputSizes = sys.inputsizes; | |
97 outputSizes = sys.outputsizes; %#ok<NASGU> | |
98 | |
99 Naos_in = inputSizes(1); | |
100 Nnoise = inputSizes(2); | |
101 NPZmodels = inputSizes(3); | |
102 | |
103 %% retrieving frequency vector | |
104 if isempty(Naos_in)==0 | |
105 f1 = find(pl,'f1'); | |
106 f2 = find(pl,'f2'); | |
107 NFreqs = find(pl,'nf'); | |
108 if isempty(f1) || isempty(f2)|| isempty(NFreqs) | |
109 error('### Please specify frequency vector a start and stop frequency .'); | |
110 else | |
111 freqs = 10 .^ linspace(log10(f1), log10(f2), NFreqs); | |
112 end | |
113 else | |
114 freqs = aos_in(1).x; | |
115 end | |
116 | |
117 %% checking frequency vector | |
118 for i=2:numel(aos_in) | |
119 if ~isequal(freqs,aos_in(i).x) | |
120 error('there exist different frequency vectors'); | |
121 end | |
122 end | |
123 | |
124 %% reshape pzmodels and aos for input cross-spectra | |
125 if numel(PZ_in)==NPZmodels | |
126 PZdata = zeros(NPZmodels,NFreqs); | |
127 for i=1:NPZmodels | |
128 a = resp(PZ_in(i), freqs); | |
129 PZdata(i,:) = reshape(a.y,[1,NFreqs]) ; | |
130 end | |
131 else | |
132 error('Wrong size for field PZ_in') | |
133 end | |
134 | |
135 if numel(aos_in)==Naos_in | |
136 AOdata = zeros(Naos_in,NFreqs); | |
137 for i=1:Naos_in | |
138 AOdata(i,:) = reshape(aos_in(i).y,[1,NFreqs]) ; | |
139 end | |
140 else | |
141 error('Wrong size for field aos_in') | |
142 end | |
143 | |
144 %% SSM Transfer function | |
145 [a, b, c, d, Ts, InputName, StateName, OutputName,... | |
146 inputvarunits, ssvarunits, outputvarunits] = double(sys); %#ok<ASGLU> | |
147 resps = ssm.doBode(a, b, c, d, 2*pi*freqs, Ts); | |
148 Noutputs = numel(OutputName); | |
149 | |
150 %% power for each frequency with SVD computation | |
151 diagOnly = pl.find('DIAGONAL ONLY'); | |
152 if diagOnly | |
153 Result = zeros(Noutputs, Nnoise+Naos_in+NPZmodels, NFreqs); | |
154 else | |
155 Result = zeros(Noutputs, Noutputs, Nnoise+Naos_in+NPZmodels, NFreqs); | |
156 end | |
157 | |
158 for ff=1:NFreqs | |
159 for ii = 1:(Nnoise+Naos_in+NPZmodels) | |
160 powWhiteNoise = zeros(1,Nnoise); | |
161 powAO = zeros(1, Naos_in); | |
162 powPZ = zeros(1,NPZmodels); | |
163 if ii<Nnoise+1, | |
164 %% contribution from white noise | |
165 powWhiteNoise(ii) = noise_mat(ii) ; | |
166 elseif ii<Nnoise+Naos_in+1 | |
167 %% contribution from aos | |
168 i_input2 = ii-Nnoise; | |
169 if AOdata(i_input2,ff)<0 | |
170 error('input PSD is not positive!') | |
171 end | |
172 powAO(i_input2) = AOdata(i_input2,ff); | |
173 else | |
174 %% contribution from PZmodels | |
175 i_input2 = ii-Nnoise-Naos_in; | |
176 if PZdata(i_input2,ff)<0 | |
177 error('input PSD is not positive!') | |
178 end | |
179 powPZ(i_input2) = real( PZdata(i_input2,ff) * conj( PZdata(i_input2,ff)) ); | |
180 end | |
181 %% computing CPSD | |
182 pow = diag([powAO; powWhiteNoise; powPZ]); | |
183 RespLoc = squeeze(resps(:,:,ff)); | |
184 noise = RespLoc * pow * RespLoc' * (2*timestep); | |
185 if diagOnly | |
186 Result(:,ii,ff) = real(diag(noise)); | |
187 else | |
188 Result(:,:,ii,ff) = noise; | |
189 end | |
190 | |
191 end | |
192 end | |
193 | |
194 %% saving in aos | |
195 if diagOnly | |
196 ao_outSum = ao.initObjectWithSize(Noutputs, 1); | |
197 %% sum of all inputs | |
198 for oo=1:Noutputs | |
199 ao_outSum(oo,1).setData(fsdata(freqs, squeeze(sum(Result(oo,:,:),2)) )); | |
200 ao_outSum(oo,1).setName( ['PSD of ' , OutputName{oo} ' due to all contributions']); | |
201 ao_outSum(oo,1).setXunits('Hz'); | |
202 ao_outSum(oo,1).setYunits(outputvarunits(oo)^2/unit('Hz')); | |
203 ao_outSum(oo,1).setDescription( ['PSD of ' , OutputName{oo} ' due to all contributions']); | |
204 end | |
205 if nargout ~= 1; | |
206 ao_out = ao.initObjectWithSize(Noutputs, Nnoise+Naos_in+NPZmodels); | |
207 %% individual inputs | |
208 for oo=1:Noutputs | |
209 for ii=1:(Nnoise+Naos_in+NPZmodels) | |
210 ao_out(oo,ii).setData(fsdata(freqs, squeeze(Result(oo,ii,:)) )); | |
211 ao_out(oo,ii).setName( ['PSD of ' , OutputName{oo} ' due to ' InputName{ii}]); | |
212 ao_out(oo,ii).setXunits('Hz'); | |
213 ao_out(oo,ii).setYunits(outputvarunits(oo)^2/unit('Hz')); | |
214 ao_out(oo,ii).setDescription( ['PSD of ' , OutputName{oo} ' due to ' InputName{ii}]); | |
215 end | |
216 end | |
217 end | |
218 else | |
219 ao_outSum = ao.initObjectWithSize(Noutputs, Noutputs); | |
220 %% sum of all inputs | |
221 for oo=1:Noutputs | |
222 for pp=1:Noutputs | |
223 ao_outSum(oo,pp).setData(fsdata(freqs, squeeze(sum(Result(oo,pp,:,:),3)) )); | |
224 ao_outSum(oo,pp).setXunits('Hz'); | |
225 ao_outSum(oo,pp).setYunits(outputvarunits(oo)^2/unit('Hz')); | |
226 if oo~=pp | |
227 ao_outSum(oo,pp).setName( ['Cross PSD of ', OutputName{oo}, ' and ', OutputName{pp} ' due to all contributions']); | |
228 ao_outSum(oo,pp).setDescription( ['Cross PSD of ', OutputName{oo}, ' and ', OutputName{pp} ' due to all contributions']); | |
229 else | |
230 ao_outSum(oo,pp).setName( ['PSD of ' , OutputName{oo}]); | |
231 ao_outSum(oo,pp).setDescription( ['PSD of ' , OutputName{oo}]); | |
232 end | |
233 end | |
234 end | |
235 if nargout ~= 1; | |
236 ao_out = ao.initObjectWithSize(Noutputs, Noutputs, Nnoise+Naos_in+NPZmodels); | |
237 %% individual inputs | |
238 for oo=1:Noutputs | |
239 for pp=1:Noutputs | |
240 for ii=1:(Nnoise+Naos_in+NPZmodels) | |
241 ao_out(oo,pp,ii).setData(fsdata(freqs, squeeze(Result(oo,pp,ii,:)) )); | |
242 ao_out(oo,pp,ii).setXunits('Hz'); | |
243 ao_out(oo,pp,ii).setYunits(outputvarunits(oo)^2/unit('Hz')); | |
244 if oo~=pp | |
245 ao_out(oo,pp,ii).setName( ['Cross PSD of ', OutputName{oo}, ' and ', OutputName{pp} ' due to ' InputName{ii}]); | |
246 ao_out(oo,pp,ii).setDescription( ['Cross PSD of ', OutputName{oo}, ' and ', OutputName{pp} ' due to ' InputName{ii}]); | |
247 else | |
248 ao_out(oo,pp,ii).setName( ['PSD of ' , OutputName{oo} ' due to ' InputName{ii}]); | |
249 ao_out(oo,pp,ii).setDescription( ['PSD of ' , OutputName{oo} ' due to ' InputName{ii}]); | |
250 end | |
251 end | |
252 end | |
253 end | |
254 end | |
255 end | |
256 | |
257 | |
258 | |
259 %% construct output matrix object | |
260 if nargout ~= 1; | |
261 out = matrix(ao_out); | |
262 end | |
263 outSum = matrix(ao_outSum); | |
264 if callerIsMethod | |
265 % do nothing | |
266 else | |
267 myinfo = getInfo('None'); | |
268 if nargout ~= 1; | |
269 out.addHistory(myinfo, pl , ssm_invars(1), inhist ); | |
270 end | |
271 outSum.addHistory(myinfo, pl , ssm_invars(1), inhist ); | |
272 end | |
273 | |
274 %% Set output depending on nargout | |
275 if nargout == 1; | |
276 varargout = {outSum}; | |
277 elseif nargout == 2; | |
278 varargout = {outSum out }; | |
279 elseif nargout == 0; | |
280 iplot(ao_outSum, ao_out); | |
281 else | |
282 error('Wrong number of outputs') | |
283 end | |
284 end | |
285 | |
286 | |
287 | |
288 | |
289 %-------------------------------------------------------------------------- | |
290 % Get Info Object | |
291 %-------------------------------------------------------------------------- | |
292 function ii = getInfo(varargin) | |
293 | |
294 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
295 sets = {}; | |
296 pl = []; | |
297 else | |
298 sets = {'Default'}; | |
299 pl = getDefaultPlist; | |
300 end | |
301 % Build info object | |
302 ii = minfo(mfilename, 'ssm', 'ltpda', utils.const.categories.op, '$Id: cpsdForIndependentInputs.m,v 1.2 2011/05/23 14:18:20 adrien Exp $', sets, pl); | |
303 | |
304 end | |
305 | |
306 %-------------------------------------------------------------------------- | |
307 % Get Default Plist | |
308 %-------------------------------------------------------------------------- | |
309 function pl = getDefaultPlist() | |
310 pl = ssm.getInfo('reorganize', 'for cpsdForIndependentInputs').plists; | |
311 pl.remove('set'); | |
312 | |
313 p = param({'variance', 'The variance vector of this noise between input ports for the <i>time-discrete</i> noise model. '}, []); | |
314 pl.append(p); | |
315 | |
316 p = param({'PSD', 'The one sided psd vector of the white noise between input ports.'}, []); | |
317 pl.append(p); | |
318 | |
319 p = param({'aos', 'A vector of input PSD AOs, The spectrum of this noise between input ports for the <i>time-continuous</i> noise model.'}, ao.initObjectWithSize(1,0)); | |
320 pl.append(p); | |
321 | |
322 p = param({'PZmodels', 'vector of noise shape filters for the different corresponding inputs.'}, paramValue.DOUBLE_VALUE(zeros(0,1))); | |
323 pl.append(p); | |
324 | |
325 p = param({'reorganize', 'When set to 0, this means the ssm does not need be modified to match the requested i/o. Faster but dangerous!'}, paramValue.TRUE_FALSE); | |
326 pl.append(p); | |
327 | |
328 p = param({'f2', 'The maximum frequency. Default is Nyquist or 1Hz.'}, paramValue.EMPTY_DOUBLE); | |
329 pl.append(p); | |
330 | |
331 p = param({'f1', 'The minimum frequency. Default is f2*1e-5.'}, paramValue.EMPTY_DOUBLE); | |
332 pl.append(p); | |
333 | |
334 p = param({'nf', 'The number of frequency bins. Frequencies are scale logarithmically'}, paramValue.DOUBLE_VALUE(200)); | |
335 pl.append(p); | |
336 | |
337 p = param({'diagonal only', 'Set to true if you want the PSD instead of the CPSD'}, paramValue.TRUE_FALSE); | |
338 pl.append(p); | |
339 | |
340 end | |
341 |