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