Mercurial > hg > ltpda
comparison m-toolbox/classes/@ao/fngen.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 % FNGEN creates an arbitrarily long time-series based on the input PSD. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: FNGEN creates an arbitrarily long time-series based on the input PSD. | |
5 % | |
6 % CALL: b = fngen(axx, pl) | |
7 % | |
8 % PARAMETERS: | |
9 % 'Nsecs' - The number of seconds to produce | |
10 % [default: inverse of PSD length] | |
11 % 'Win' - The spectral window to use for blending segments | |
12 % [default: Kaiser -150dB] | |
13 % | |
14 % | |
15 % NOTE: this function requires the Statistics Toolbox in order to create | |
16 % a chi^2 distributed random variable. | |
17 % | |
18 % <a href="matlab:utils.helper.displayMethodInfo('ao', 'fngen')">Parameters Description</a> | |
19 % | |
20 % VERSION: $Id: fngen.m,v 1.33 2011/04/08 08:56:16 hewitson Exp $ | |
21 % | |
22 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
23 | |
24 function varargout = fngen(varargin) | |
25 | |
26 % Check if this is a call for parameters | |
27 if utils.helper.isinfocall(varargin{:}) | |
28 varargout{1} = getInfo(varargin{3}); | |
29 return | |
30 end | |
31 | |
32 import utils.const.* | |
33 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); | |
34 | |
35 % Collect input variable names | |
36 in_names = cell(size(varargin)); | |
37 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
38 | |
39 % Collect all AOs and plists | |
40 [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); | |
41 pl = utils.helper.collect_objects(varargin(:), 'plist', in_names); | |
42 | |
43 if nargout == 0 | |
44 error('### fngen cannot be used as a modifier. Please give an output variable.'); | |
45 end | |
46 | |
47 % combine plists | |
48 pl = parse(pl, getDefaultPlist()); | |
49 | |
50 % Extract necessary parameters | |
51 Nsecs = find(pl, 'Nsecs'); | |
52 swin = find(pl, 'win'); | |
53 | |
54 % Loop over input AOs | |
55 bs = []; | |
56 for j=1:numel(as) | |
57 if ~isa(as(j).data, 'fsdata') | |
58 warning('!!! %s expects ao/fsdata objects. Skipping AO %s', mfilename, as(j).name); | |
59 else | |
60 % Properties of the input PSD | |
61 N = 2*(length(as(j).data.y)-1); | |
62 fs = as(j).data.x(end)*2; | |
63 % Extract Fourier components | |
64 Ak = sqrt(N*as(j).data.getY*fs); | |
65 Ak = [Ak; Ak(end-1:-1:2)]; % make two-sided | |
66 % redesign input window for this length | |
67 switch lower(swin.type) | |
68 case 'kaiser' | |
69 swin = specwin('Kaiser', N, swin.psll); | |
70 otherwise | |
71 swin = specwin(swin.type, N); | |
72 end | |
73 % Compute time-series segments | |
74 Olap = 1-swin.rov/100; | |
75 win = [swin.win].'; | |
76 segLen = N/fs; | |
77 if segLen > Nsecs | |
78 cNsecs = 2*segLen; | |
79 else | |
80 cNsecs = Nsecs; | |
81 end | |
82 Nsegs = 1+floor(cNsecs/segLen/Olap); | |
83 | |
84 % Prepare for generation | |
85 rphi = zeros(N,1); % Empty vector for random phases | |
86 xs = zeros(fs*(cNsecs+segLen), 1); % Large empty vector for new time-series | |
87 e1 = 1; e2 = segLen*fs; % Indices into large vector | |
88 step = round(segLen*fs*Olap); % step size between each new segment | |
89 lxs = length(xs); | |
90 | |
91 % Loop over segments | |
92 for s=1:Nsegs | |
93 % Generate random phase vector | |
94 rphi(2:N/2) = pi*rand(1,N/2-1); % First half | |
95 rphi(N/2+1) = pi*round(rand); % mid point | |
96 rphi(N/2+2:N) = -rphi(N/2:-1:2); % reflected half | |
97 %---- Compute Fourier amplitudes | |
98 % Use chi^2 distribution to randomize amplitudes. | |
99 % - from Percival and Walden: S_est = S.*chi2rnd(2)/2 | |
100 % so A_est = A.*sqrt(chi2rnd(2)/2) | |
101 % Here we take the measured input data to be a good estimate of | |
102 % the underlying power spectrum | |
103 X = (Ak.*sqrt(chi2rnd(2)/2)) .*exp(1i.*rphi); | |
104 % Inverse FFT | |
105 x = ifft(X, 'symmetric'); | |
106 % overlap the segments | |
107 xs(e1:e2) = xs(e1:e2) + win.*x; | |
108 % increase step | |
109 e1 = e1 + step; | |
110 e2 = e2 + step; | |
111 if e2>lxs | |
112 break | |
113 end | |
114 end | |
115 % Make ao from the segment of data we want | |
116 e1 = fs*segLen/2; | |
117 e2 = fs*(Nsecs+segLen/2)-1; | |
118 b = ao(tsdata(xs(e1:e2).', fs)); | |
119 b.name = sprintf('fngen(%s)', ao_invars{j}); | |
120 b.data.setXunits('s'); | |
121 % Add history | |
122 b.addHistory(getInfo('None'), pl, ao_invars(j), as(j).hist); | |
123 % Add to outputs | |
124 bs = [bs b]; | |
125 end | |
126 end | |
127 | |
128 % Set output | |
129 if nargout == numel(bs) | |
130 % List of outputs | |
131 for ii = 1:numel(bs) | |
132 varargout{ii} = bs(ii); | |
133 end | |
134 else | |
135 % Single output | |
136 varargout{1} = bs; | |
137 end | |
138 | |
139 end | |
140 | |
141 %-------------------------------------------------------------------------- | |
142 % Get Info Object | |
143 %-------------------------------------------------------------------------- | |
144 function ii = getInfo(varargin) | |
145 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
146 sets = {}; | |
147 pl = []; | |
148 else | |
149 sets = {'Default'}; | |
150 pl = getDefaultPlist; | |
151 end | |
152 % Build info object | |
153 ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.sigproc, '$Id: fngen.m,v 1.33 2011/04/08 08:56:16 hewitson Exp $', sets, pl); | |
154 ii.setModifier(false); | |
155 end | |
156 | |
157 %-------------------------------------------------------------------------- | |
158 % Get Default Plist | |
159 %-------------------------------------------------------------------------- | |
160 function plout = getDefaultPlist() | |
161 persistent pl; | |
162 if exist('pl', 'var')==0 || isempty(pl) | |
163 pl = buildplist(); | |
164 end | |
165 plout = pl; | |
166 end | |
167 | |
168 function pl = buildplist() | |
169 | |
170 pl = plist(); | |
171 | |
172 % Win | |
173 p = param({'Win', 'The spectral window to use for blending data segments.'}, paramValue.WINDOW); | |
174 pl.append(p); | |
175 | |
176 % Nsecs | |
177 p = param({'Nsecs', 'The number of seconds of data to produce.'}, paramValue.EMPTY_DOUBLE); | |
178 pl.append(p); | |
179 | |
180 end | |
181 |