Mercurial > hg > ltpda
comparison m-toolbox/classes/@matrix/tdfit.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 % TDFIT fit a MATRIX of transfer function SMODELs to a matrix of input and output signals. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: TDFIT fits a MATRIX of transfer function SMODELs to a set of | |
5 % input and output signals. It uses ao\tdfit as the core algorithm. | |
6 % | |
7 % | |
8 % CALL: b = tdfit(outputs, pl) | |
9 % | |
10 % INPUTS: outputs - an array of MATRIXs representing the outputs of a system, | |
11 % one per each experiment. | |
12 % pl - parameter list (see below) | |
13 % | |
14 % OUTPUTs: b - a pest object containing the best-fit parameters, | |
15 % goodness-of-fit reduced chi-squared, fit degree-of-freedom | |
16 % covariance matrix and uncertainties. Additional | |
17 % quantities, like the Information Matrix, are contained | |
18 % within the procinfo. The best-fit model can be evaluated | |
19 % from pest\eval. | |
20 % | |
21 % <a href="matlab:utils.helper.displayMethodInfo('matrix', 'tdfit')">Parameters Description</a> | |
22 % | |
23 % EXAMPLES: | |
24 % | |
25 % VERSION: $Id: tdfit.m,v 1.9 2011/04/08 08:56:31 hewitson Exp $ | |
26 % | |
27 % HISTORY: 09-02-2011 G. Congedo | |
28 % | |
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
30 | |
31 function varargout = tdfit(varargin) | |
32 | |
33 % Check if this is a call for parameters | |
34 if utils.helper.isinfocall(varargin{:}) | |
35 varargout{1} = getInfo(varargin{3}); | |
36 return | |
37 end | |
38 | |
39 import utils.const.* | |
40 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); | |
41 | |
42 % Collect input variable names | |
43 in_names = cell(size(varargin)); | |
44 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
45 | |
46 % Collect all ltpdauoh objects | |
47 [mtxs, mtxs_invars] = utils.helper.collect_objects(varargin(:), 'matrix', in_names); | |
48 [pl, invars] = utils.helper.collect_objects(varargin(:), 'plist'); | |
49 | |
50 % combine plists | |
51 pl = parse(pl, getDefaultPlist()); | |
52 | |
53 if nargout == 0 | |
54 error('### tdfit cannot be used as a modifier. Please give an output variable.'); | |
55 end | |
56 | |
57 % combine plists | |
58 pl = parse(pl, getDefaultPlist()); | |
59 | |
60 % Extract necessary parameters | |
61 inputs = pl.find('inputs'); | |
62 TFmodels = pl.find('models'); | |
63 WhFlts = pl.find('WhFlts'); | |
64 inNames = pl.find('innames'); | |
65 outNames = pl.find('outnames'); | |
66 P0 = pl.find('P0'); | |
67 pnames = pl.find('pnames'); | |
68 | |
69 % Checks | |
70 if ~isa(mtxs,'matrix') | |
71 error('### Please, give the system outputs as an array of MATRIXs per each experiment.'); | |
72 end | |
73 if ~isa(inputs,'collection') && any(~isa(inputs.objs,'matrix')) | |
74 error('### Please, give the system inputs as a COLLECTION of MATRIXs per each experiment.'); | |
75 end | |
76 if ~isa(TFmodels,'ssm') && ~isa(TFmodels,'matrix') && any(~isa(TFmodels.objs,'smodel')) | |
77 error('### Please, give the system transfer functions as a MATRIX of SMODELs, or a single SSM model.'); | |
78 end | |
79 if ~isa(WhFlts,'matrix') && any(~isa(WhFlts.objs,'filterbank')) | |
80 error('### Please, give the system inputs as a MATRIX of FILTERBANKs.'); | |
81 end | |
82 | |
83 % Define constants | |
84 Nexp = numel(mtxs); | |
85 | |
86 % Prepare objects for fit | |
87 outputs2fit = prepare2fit(mtxs,'outputs',Nexp); | |
88 inputs2fit = prepare2fit(inputs,'inputs',Nexp); | |
89 WhFlts2fit = prepare2fit(WhFlts,'filters',Nexp); | |
90 if ~isa(TFmodels,'ssm') | |
91 models2fit = prepare2fit(TFmodels,'models',Nexp); | |
92 else | |
93 models2fit = TFmodels; | |
94 end | |
95 inNames2fit = prepare2fit(inNames,'inNames',Nexp); | |
96 outNames2fit = prepare2fit(outNames,'outNames',Nexp); | |
97 | |
98 % fit plist | |
99 fitpl = pl.pset('inputs', inputs2fit,... | |
100 'models', models2fit,... | |
101 'WhFlts', WhFlts2fit,... | |
102 'inNames', inNames2fit,... | |
103 'outNames', outNames2fit,... | |
104 'P0', P0,... | |
105 'pnames', pnames); | |
106 | |
107 % do fit | |
108 params = tdfit(outputs2fit, fitpl); | |
109 | |
110 % Make output pest | |
111 out = copy(params,1); | |
112 | |
113 % Set Name and History | |
114 mdlname = char(TFmodels(1).name); | |
115 for kk=2:numel(TFmodels) | |
116 mdlname = strcat(mdlname,[',' char(TFmodels(kk).name)]); | |
117 end | |
118 out.name = sprintf('tdfit(%s)', mdlname); | |
119 out.addHistory(getInfo('None'), pl, mtxs_invars(:), [mtxs(:).hist]); | |
120 | |
121 % Set outputs | |
122 if nargout > 0 | |
123 varargout{1} = out; | |
124 end | |
125 end | |
126 | |
127 %-------------------------------------------------------------------------- | |
128 % Included Functions | |
129 %-------------------------------------------------------------------------- | |
130 | |
131 function obj2fit = prepare2fit(obj,type,Nexp) | |
132 switch type | |
133 case 'outputs' | |
134 obj2fit = obj(1).objs; | |
135 case 'inputs' | |
136 obj2fit = obj.objs{1}.objs; | |
137 case 'filters' | |
138 obj2fit = obj.objs; | |
139 case 'inNames' | |
140 obj2fit = obj; | |
141 case 'outNames' | |
142 obj2fit = obj; | |
143 end | |
144 if exist('obj2fit','var') | |
145 if size(obj2fit)~=[numel(obj2fit),1] | |
146 obj2fit = obj2fit'; | |
147 end | |
148 for ii=2:Nexp | |
149 switch type | |
150 case 'outputs' | |
151 obj2cat = obj(ii).objs; | |
152 case 'inputs' | |
153 obj2cat = obj.objs{ii}.objs; | |
154 case 'filters' | |
155 obj2cat = obj.objs; | |
156 case 'inNames' | |
157 obj2cat = obj; | |
158 case 'outNames' | |
159 obj2cat = obj; | |
160 end | |
161 if size(obj2cat)~=[numel(obj2cat),1] | |
162 obj2cat = obj2cat'; | |
163 end | |
164 obj2fit = [obj2fit;obj2cat]; | |
165 end | |
166 end | |
167 if strcmp(type,'models') | |
168 obj2fit = smodel(); | |
169 % obj2fit.setXvar(); | |
170 sz = size(obj.objs); | |
171 obj2fit = repmat(obj2fit,Nexp*sz); | |
172 for ii=1:Nexp | |
173 obj2fit((1:sz(1))+(ii-1)*sz(1),(1:sz(2))+(ii-1)*sz(2)) = obj.objs; | |
174 end | |
175 end | |
176 end | |
177 | |
178 %-------------------------------------------------------------------------- | |
179 % Get Info Object | |
180 %-------------------------------------------------------------------------- | |
181 function ii = getInfo(varargin) | |
182 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
183 sets = {}; | |
184 pl = []; | |
185 else | |
186 sets = {'Default'}; | |
187 pl = getDefaultPlist; | |
188 end | |
189 % Build info object | |
190 ii = minfo(mfilename, 'matrix', 'ltpda', utils.const.categories.sigproc, '$Id: tdfit.m,v 1.9 2011/04/08 08:56:31 hewitson Exp $', sets, pl); | |
191 ii.setModifier(false); | |
192 end | |
193 | |
194 %-------------------------------------------------------------------------- | |
195 % Get Default Plist | |
196 %-------------------------------------------------------------------------- | |
197 function plout = getDefaultPlist() | |
198 persistent pl; | |
199 if exist('pl', 'var')==0 || isempty(pl) | |
200 pl = buildplist(); | |
201 end | |
202 plout = pl; | |
203 end | |
204 | |
205 function pl = buildplist() | |
206 | |
207 pl = plist(); | |
208 | |
209 % Inputs | |
210 p = param({'Inputs', 'A COLLECTION of MATRIXs, one per each experiment, containing the input A0s.'}, paramValue.EMPTY_DOUBLE); | |
211 pl.append(p); | |
212 | |
213 % Models | |
214 p = param({'Models', 'A MATRIX of transfer function SMODELs.'}, paramValue.EMPTY_DOUBLE); | |
215 pl.append(p); | |
216 | |
217 % PadRatio | |
218 p = param({'PadRatio', ['PadRatio is defined as the ratio between the number of zero-pad points '... | |
219 'and the data length.<br>'... | |
220 'Define how much to zero-pad data after the signal.<br>'... | |
221 'Being <tt>tdfit</tt> a fft-based algorithm, no zero-padding might bias the estimation, '... | |
222 'therefore it is strongly suggested to do that.']}, 1); | |
223 pl.append(p); | |
224 | |
225 % Whitening Filters | |
226 p = param({'WhFlts', 'A MATRIX of FILTERBANKs containing the whitening filters per each output AO.'}, paramValue.EMPTY_DOUBLE); | |
227 pl.append(p); | |
228 | |
229 % Parameters | |
230 p = param({'Pnames', 'A cell-array of parameter names to fit.'}, paramValue.EMPTY_CELL); | |
231 pl.append(p); | |
232 | |
233 % P0 | |
234 p = param({'P0', 'An array of starting guesses for the parameters.'}, paramValue.EMPTY_DOUBLE); | |
235 pl.append(p); | |
236 | |
237 % LB | |
238 p = param({'LB', ['Lower bounds for the parameters.<br>'... | |
239 'This improves convergency. Mandatory for Monte Carlo.']}, paramValue.EMPTY_DOUBLE); | |
240 pl.append(p); | |
241 | |
242 % UB | |
243 p = param({'UB', ['Upper bounds for the parameters.<br>'... | |
244 'This improves the convergency. Mandatory for Monte Carlo.']}, paramValue.EMPTY_DOUBLE); | |
245 pl.append(p); | |
246 | |
247 % Algorithm | |
248 p = param({'ALGORITHM', ['A string defining the fitting algorithm.<br>'... | |
249 '<tt>fminunc</tt>, <tt>fmincon</tt> require ''Optimization Toolbox'' to be installed.<br>'... | |
250 '<tt>patternsearch</tt>, <tt>ga</tt>, <tt>simulannealbnd</tt> require ''Genetic Algorithm and Direct Search'' to be installed.<br>']}, ... | |
251 {1, {'fminsearch', 'fminunc', 'fmincon', 'patternsearch', 'ga', 'simulannealbnd'}, paramValue.SINGLE}); | |
252 pl.append(p); | |
253 | |
254 % OPTSET | |
255 p = param({'OPTSET', ['An optimisation structure to pass to the fitting algorithm.<br>'... | |
256 'See <tt>fminsearch</tt>, <tt>fminunc</tt>, <tt>fmincon</tt>, <tt>optimset</tt>, for details.<br>'... | |
257 'See <tt>patternsearch</tt>, <tt>psoptimset</tt>, for details.<br>'... | |
258 'See <tt>ga</tt>, <tt>gaoptimset</tt>, for details.<br>'... | |
259 'See <tt>simulannealbnd</tt>, <tt>saoptimset</tt>, for details.']}, paramValue.EMPTY_STRING); | |
260 pl.append(p); | |
261 | |
262 % SymDiff | |
263 p = param({'SymDiff', 'Use symbolic derivatives or not. Only for gradient-based algorithm or for LinUnc option.'}, paramValue.NO_YES); | |
264 pl.append(p); | |
265 | |
266 % DiffOrder | |
267 p = param({'DiffOrder', 'Symbolic derivative order. Only for SymDiff option.'}, {1, {1,2}, paramValue.SINGLE}); | |
268 pl.append(p); | |
269 | |
270 % FitUnc | |
271 p = param({'FitUnc', 'Fit parameter uncertainties or not.'}, paramValue.YES_NO); | |
272 pl.append(p); | |
273 | |
274 % UncMtd | |
275 p = param({'UncMtd', ['Choose the uncertainties estimation method.<br>'... | |
276 'For multi-channel fitting <tt>hessian</tt> is mandatory.']}, {1, {'hessian', 'jacobian'}, paramValue.SINGLE}); | |
277 pl.append(p); | |
278 | |
279 % LinUnc | |
280 p = param({'LinUnc', 'Force linear symbolic uncertainties.'}, paramValue.YES_NO); | |
281 pl.append(p); | |
282 | |
283 % GradSearch | |
284 p = param({'GradSearch', 'Do a preliminary gradient-based search using the BFGS Quasi-Newton method.'}, paramValue.NO_YES); | |
285 pl.append(p); | |
286 | |
287 % MonteCarlo | |
288 p = param({'MonteCarlo', ['Do a Monte Carlo search in the parameter space.<br>'... | |
289 'Useful when dealing with high multiplicity of local minima. May be computer-expensive.<br>'... | |
290 'Note that, if used, P0 will be ignored. It also requires to define LB and UB.']}, paramValue.NO_YES); | |
291 pl.append(p); | |
292 | |
293 % Npoints | |
294 p = param({'Npoints', 'Set the number of points in the parameter space to be extracted.'}, 100000); | |
295 pl.append(p); | |
296 | |
297 % Noptims | |
298 p = param({'Noptims', 'Set the number of optimizations to be performed after the Monte Carlo.'}, 10); | |
299 pl.append(p); | |
300 | |
301 end | |
302 % END |