Mercurial > hg > ltpda
comparison m-toolbox/classes/@ao/join.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 % JOIN multiple AOs into a single AO. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: JOIN multiple AOs into a single AO. | |
5 % If any two AOs overlap, then the values from the first appear | |
6 % in the output AO. | |
7 % | |
8 % Note: If the input AOs are of type 'tsdata', then they will | |
9 % be sorted in ascending order according the t0 of each | |
10 % object. | |
11 % | |
12 % | |
13 % CALL: bs = join(a1,a2,a3,...,pl) | |
14 % bs = join(as,pl) | |
15 % bs = as.join(pl) | |
16 % | |
17 % INPUTS: aN - input analysis objects | |
18 % as - input analysis objects array | |
19 % pl - input parameter list | |
20 % | |
21 % OUTPUTS: b - output analysis object | |
22 % | |
23 % <a href="matlab:utils.helper.displayMethodInfo('ao', 'join')">Parameters Description</a> | |
24 % | |
25 % REMARK: Input AOs should be of the same type; if not, only AOs of the | |
26 % type of the first input AO will be joined together to produce | |
27 % the output. | |
28 % | |
29 % VERSION: $Id: join.m,v 1.60 2011/09/02 11:11:51 ingo Exp $ | |
30 % | |
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
32 | |
33 % PARAMETERS: 'zerofill' - Fills with zeros the gaps between the data | |
34 % points of the subsequent aos. [Default: 'no'] | |
35 % 'sameT0' - Does not recalculate t0 but uses the common | |
36 % one. [Default: 'no'] | |
37 % Note: the t0 among different objects must be the same! | |
38 % | |
39 | |
40 function varargout = join(varargin) | |
41 | |
42 % Check if this is a call for parameters | |
43 if utils.helper.isinfocall(varargin{:}) | |
44 varargout{1} = getInfo(varargin{3}); | |
45 return | |
46 end | |
47 | |
48 import utils.const.* | |
49 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); | |
50 | |
51 % Collect input variable names | |
52 in_names = cell(size(varargin)); | |
53 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
54 | |
55 % Collect all AOs | |
56 [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); | |
57 pl = utils.helper.collect_objects(varargin(:), 'plist', in_names); | |
58 | |
59 % Combine plists | |
60 pl = parse(pl, getDefaultPlist); | |
61 | |
62 | |
63 | |
64 %---------------------------------------------- | |
65 % Get data type from the first AO | |
66 dtype = class(as(1).data); | |
67 | |
68 % Sort the input AOs by t0, if applicable | |
69 if strcmp(dtype, 'tsdata') | |
70 times = as.t0.double; | |
71 [~, idx] = sort(times); | |
72 as = as(idx); | |
73 end | |
74 | |
75 %---------------------------------------------- | |
76 % Go through each AO and collect the data of type 'dtype' | |
77 | |
78 histin = []; | |
79 xo = []; | |
80 yo = []; | |
81 dxo = []; | |
82 dyo = []; | |
83 enbw0 = []; | |
84 fs = -1; | |
85 aname = ''; | |
86 adescr = ''; | |
87 plotinfo = []; | |
88 if as(1).data.isprop('xunits') | |
89 xunitsSimple = simplify(as(1).data.xunits); | |
90 xunits = as(1).data.xunits; | |
91 end | |
92 yunitsSimple = simplify(as(1).data.yunits); | |
93 yunits = as(1).data.yunits; | |
94 | |
95 % Get the tolerance for considering fs equal | |
96 fstol = find(pl, 'fstol'); | |
97 | |
98 % Compute time offset for tsdata objects to avoid rounding errors later | |
99 minT0milli = getMinT0(as); | |
100 | |
101 % loop over AOs | |
102 for jj=1:numel(as) | |
103 % Only get the data type we want | |
104 if isa(as(jj).data, dtype) | |
105 switch lower(dtype) | |
106 case 'tsdata' | |
107 % here we concatonate time-series | |
108 t0 = (as(jj).data.t0.utc_epoch_milli - minT0milli)/1000; | |
109 % make proper time vector | |
110 x = as(jj).x + t0; | |
111 | |
112 % only add samples past the end of existing (first loop) | |
113 if isempty(xo) | |
114 yo = as(jj).y; | |
115 xo = x; | |
116 if numel(as(jj).dx) == 0 | |
117 dxo = zeros(numel(as(jj).x),1); | |
118 elseif numel(as(jj).dx) == 1 | |
119 dxo = ones(numel(as(jj).x),1) .* as(jj).dx; | |
120 else | |
121 dxo = as(jj).dx; | |
122 end | |
123 if numel(as(jj).dy) == 0 | |
124 dyo = zeros(numel(as(jj).y),1); | |
125 elseif numel(as(jj).dy) == 1 | |
126 dyo = ones(numel(as(jj).y),1) .* as(jj).dy; | |
127 else | |
128 dyo = as(jj).dy; | |
129 end | |
130 else | |
131 idxPost = find(x > max(xo)); | |
132 idxPre = find(x < min(xo)); | |
133 | |
134 %%%%%%%%%% Fill the gaps with zeros %%%%%%%%%% | |
135 zerofill = utils.prog.yes2true(find(pl, 'zerofill')); | |
136 | |
137 if zerofill | |
138 % Check if there is a gap between the x-values and the pre-values. | |
139 if ~isempty(idxPre) | |
140 interStart = x(idxPre(end)); | |
141 interEnd = xo(1); | |
142 nsecsPre2no = interEnd - interStart; | |
143 | |
144 % The gap must be larger than 1/fs in order to | |
145 % fill the gap with zeros | |
146 if nsecsPre2no > 1/fs | |
147 x_interPre = linspace(interStart+1/fs, interEnd-1/fs, nsecsPre2no*fs-2*1/fs).'; | |
148 y_interPre = zeros(length(x_interPre), 1); | |
149 else | |
150 x_interPre = []; | |
151 y_interPre = []; | |
152 end | |
153 else | |
154 x_interPre = []; | |
155 y_interPre = []; | |
156 end | |
157 | |
158 % Check if there is a gap between the x-values and the post-values. | |
159 if ~isempty(idxPost) | |
160 interStart = xo(end); | |
161 interEnd = x(idxPost(1)); | |
162 nsecsPost2no = interEnd - interStart; | |
163 | |
164 % The gap must be larger than 1/fs in order to | |
165 % fill the gap with zeros | |
166 if nsecsPost2no > 1/fs | |
167 x_interPost = linspace(interStart+1/fs, interEnd-1/fs, nsecsPost2no*fs-1/fs).'; | |
168 y_interPost = zeros(length(x_interPost), 1); | |
169 else | |
170 x_interPost = []; | |
171 y_interPost = []; | |
172 end | |
173 else | |
174 x_interPost = []; | |
175 y_interPost = []; | |
176 end | |
177 | |
178 else | |
179 %%%%%%%%%% Don't fill the gaps with zeros %%%%%%%%%% | |
180 x_interPre = []; | |
181 y_interPre = []; | |
182 x_interPost = []; | |
183 y_interPost = []; | |
184 end | |
185 xo = [x(idxPre); x_interPre; xo; x_interPost; x(idxPost)]; | |
186 yo = [as(jj).data.getY(idxPre); y_interPre; yo; y_interPost; as(jj).data.getY(idxPost)]; | |
187 | |
188 %%% Collect errors | |
189 if numel(as(jj).dx) == 0 | |
190 dx = zeros(numel(as(jj).x),1); | |
191 elseif numel(as(jj).dx) == 1 | |
192 dx = ones(numel(as(jj).x),1) .* as(jj).dx; | |
193 else | |
194 dx = as(jj).dx; | |
195 end | |
196 | |
197 if numel(as(jj).dy) == 0 | |
198 dy = zeros(numel(as(jj).y),1); | |
199 elseif numel(as(jj).dy) == 1 | |
200 dy = ones(numel(as(jj).y),1) .* as(jj).dy; | |
201 else | |
202 dy = [dyo; as(jj).dy]; | |
203 end | |
204 | |
205 x_interPre = zeros(numel(x_interPre),1); | |
206 y_interPre = zeros(numel(y_interPre),1); | |
207 x_interPost = zeros(numel(x_interPost),1); | |
208 y_interPost = zeros(numel(y_interPost),1); | |
209 dxo = [dx(idxPre); x_interPre; dxo; x_interPost; dx(idxPost)]; | |
210 dyo = [dy(idxPre); y_interPre; dyo; y_interPost; dy(idxPost)]; | |
211 | |
212 end | |
213 | |
214 % check fs | |
215 if (fs > 0) && (abs(as(jj).fs - fs) > fstol*fs) | |
216 error('### Data has different sample rates'); | |
217 end | |
218 % store fs | |
219 fs = as(jj).fs; | |
220 | |
221 % check xunits | |
222 if ~eq(xunitsSimple, simplify(as(jj).xunits)) | |
223 error('### The x-units of the analysis objects are not the same %s <-> %s', char(xunits), char(as(jj).xunits)); | |
224 end | |
225 % check yunits | |
226 if ~eq(yunitsSimple, simplify(as(jj).yunits)) | |
227 error('### The y-units of the analysis objects are not the same %s <-> %s', char(yunits), char(as(jj).yunits)); | |
228 end | |
229 | |
230 % store T0 | |
231 T0s(jj) = as(jj).t0; | |
232 | |
233 case 'fsdata' | |
234 | |
235 %%% Collect all fsdata samples | |
236 if isempty(xo) | |
237 idxBefore = 1:numel(as(jj).x); | |
238 idxAfter = []; | |
239 else | |
240 idxBefore = find(as(jj).x < xo(1)); | |
241 idxAfter = find(as(jj).x > xo(end)); | |
242 end | |
243 xo = [as(jj).x(idxBefore); xo; as(jj).x(idxAfter)]; | |
244 yo = [as(jj).y(idxBefore); yo; as(jj).y(idxAfter)]; | |
245 | |
246 %%% Collect all errors | |
247 % dx | |
248 if numel(as(jj).dx) == 0 | |
249 dx = zeros(numel(as(jj).x),1); | |
250 elseif numel(as(jj).dx) == 1 | |
251 dx = ones(numel(as(jj).x),1) .* as(jj).dx; | |
252 else | |
253 dx = as(jj).dx; | |
254 end | |
255 dxo = [dx(idxBefore); dxo; dx(idxAfter)]; | |
256 % dy | |
257 if numel(as(jj).dy) == 0 | |
258 dy = zeros(numel(as(jj).y),1); | |
259 elseif numel(as(jj).dy) == 1 | |
260 dy = ones(numel(as(jj).y),1) .* as(jj).dy; | |
261 else | |
262 dy = as(jj).dy; | |
263 end | |
264 dyo = [dy(idxBefore); dyo; dy(idxAfter)]; | |
265 % enbw | |
266 if numel(as(jj).data.enbw) == 0 | |
267 enbw = NaN(numel(as(jj).y),1); | |
268 elseif numel(as(jj).data.enbw) == 1 | |
269 enbw = ones(numel(as(jj).y),1) .* as(jj).data.enbw; | |
270 else | |
271 enbw = as(jj).data.enbw; | |
272 end | |
273 enbw0 = [enbw(idxBefore); enbw0; enbw(idxAfter)]; | |
274 | |
275 % check fs | |
276 if (fs > 0) && (abs(as(jj).fs - fs) > fstol*fs) | |
277 error('### Data has different sample rates'); | |
278 end | |
279 % store fs | |
280 fs = as(jj).fs; | |
281 | |
282 % check xunits | |
283 if ~eq(xunitsSimple, simplify(as(jj).xunits)) | |
284 error('### The x-units of the analysis objects are not the same %s <-> %s', char(xunits), char(as(jj).xunits)); | |
285 end | |
286 % check yunits | |
287 if ~eq(yunitsSimple, simplify(as(jj).yunits)) | |
288 error('### The y-units of the analysis objects are not the same %s <-> %s', char(yunits), char(as(jj).yunits)); | |
289 end | |
290 | |
291 case 'xydata' | |
292 xo = [xo; as(jj).x]; | |
293 yo = [yo; as(jj).y]; | |
294 if numel(as(jj).dx) == 0 | |
295 dx = zeros(numel(as(jj).x),1); | |
296 elseif numel(as(jj).dx) == 1 | |
297 dx = ones(numel(as(jj).x),1) .* as(jj).dx; | |
298 else | |
299 dx = as(jj).dx; | |
300 end | |
301 dxo = [dxo; dx]; | |
302 if numel(as(jj).dy) == 0 | |
303 dy = zeros(numel(as(jj).y),1); | |
304 elseif numel(as(jj).dy) == 1 | |
305 dy = ones(numel(as(jj).y),1) .* as(jj).dy; | |
306 else | |
307 dy = as(jj).dy; | |
308 end | |
309 dyo = [dyo; dy]; | |
310 | |
311 % check xunits | |
312 if ~eq(xunitsSimple, simplify(as(jj).xunits)) | |
313 error('### The x-units of the analysis objects are not the same %s <-> %s', char(xunits), char(as(jj).xunits)); | |
314 end | |
315 % check yunits | |
316 if ~eq(yunitsSimple, simplify(as(jj).yunits)) | |
317 error('### The y-units of the analysis objects are not the same %s <-> %s', char(yunits), char(as(jj).yunits)); | |
318 end | |
319 | |
320 case 'cdata' | |
321 try | |
322 yo = [yo; as(jj).y]; | |
323 if numel(as(jj).dy) == 0 | |
324 dy = zeros(numel(as(jj).y),1); | |
325 elseif numel(as(jj).dy) == 1 | |
326 dy = ones(numel(as(jj).y),1) .* as(jj).dy; | |
327 else | |
328 dy = as(jj).dy; | |
329 end | |
330 dyo = [dyo; dy]; | |
331 catch E | |
332 disp(E.message) | |
333 error('### It is not possible to join the data or error because they have different dimensions.'); | |
334 end | |
335 | |
336 % check yunits | |
337 if ~eq(yunitsSimple, simplify(as(jj).yunits)) | |
338 error('### The y-units of the analysis objects are not the same %s <-> %s', char(yunits), char(as(jj).yunits)); | |
339 end | |
340 | |
341 otherwise | |
342 error('### Unknown data type'); | |
343 end | |
344 % Collect this input history | |
345 histin = [histin as(jj).hist]; | |
346 % Collect the 'plotinfo' | |
347 if ~isempty(as(jj).plotinfo) | |
348 plotinfo = combine(plotinfo, as(jj).plotinfo); | |
349 end | |
350 % Collect the descriptions | |
351 adescr = strcat(adescr, as(jj).description); | |
352 % Collect names, invars | |
353 if ~isempty(aname) | |
354 if ~strcmp(aname, as(jj).name) | |
355 aname = [aname ',' as(jj).name]; | |
356 end | |
357 else | |
358 aname = as(jj).name; | |
359 end | |
360 else | |
361 warning('!!! Ignoring AO input with data type %s', dtype); | |
362 end | |
363 end | |
364 | |
365 %---------------------------------------------- | |
366 % Now sort output vectors | |
367 if ~isempty(xo) | |
368 [xos, idx] = sort(xo); | |
369 yos = yo(idx); | |
370 dxos = dxo(idx); | |
371 dyos = dyo(idx); | |
372 else | |
373 xos = xo; | |
374 yos = yo; | |
375 dxos = dxo; | |
376 dyos = dyo; | |
377 end | |
378 | |
379 if all(dxos == 0) | |
380 dxos = []; | |
381 elseif all(diff(dxos) == 0) | |
382 dxos = dxos(1); | |
383 end | |
384 if all(dyos == 0) | |
385 dyos = []; | |
386 elseif all(diff(dyos) == 0) | |
387 dyos = dyos(1); | |
388 end | |
389 | |
390 % Keep the data shape if the input AO | |
391 if size(as(1).data.y,1) == 1 | |
392 xos = xos.'; | |
393 yos = yos.'; | |
394 end | |
395 | |
396 %%% Build output data object | |
397 switch lower(dtype) | |
398 case 'tsdata' | |
399 sameT0 = utils.prog.yes2true(find(pl, 'sameT0')); | |
400 | |
401 % % Check that all objects share the t0 | |
402 % for kk = 1:numel(T0s) | |
403 % if ne(T0s(kk), T0s(1)) | |
404 % sameT0 = false; | |
405 % end | |
406 % end | |
407 % if sameT0 | |
408 % data = tsdata(xos, yos, fs); | |
409 % data.setT0(minT0milli/1000); | |
410 % else | |
411 % get t0 | |
412 % toffset = xos(1); | |
413 % xos = xos - toffset; | |
414 data = tsdata(xos, yos, fs); | |
415 data.setT0((minT0milli/1000)); | |
416 % data.setToffset(toffset*1000); | |
417 % end | |
418 data.setDx(dxos); | |
419 data.setDy(dyos); | |
420 data.setXunits(xunits); | |
421 data.setYunits(yunits); | |
422 data.collapseX; | |
423 case 'fsdata' | |
424 if all(isnan(enbw0)) | |
425 enbw0 = []; | |
426 elseif all(diff(enbw0) == 0) | |
427 enbw0 = enbw0(1); | |
428 end | |
429 data = fsdata(xos, yos); | |
430 data.setDx(dxos); | |
431 data.setDy(dyos); | |
432 data.setEnbw(enbw0); | |
433 data.setFs(fs); | |
434 data.setXunits(xunits); | |
435 data.setYunits(yunits); | |
436 case 'xydata' | |
437 data = xydata(xos, yos); | |
438 data.setDx(dxos); | |
439 data.setDy(dyos); | |
440 data.setXunits(xunits); | |
441 data.setYunits(yunits); | |
442 case 'cdata' | |
443 data = cdata(yos); | |
444 data.setDy(dyos); | |
445 data.setYunits(yunits); | |
446 end | |
447 | |
448 %---------------------------------------------- | |
449 % Build output AO | |
450 if nargout == 0 | |
451 a = as(1); | |
452 a.data = data; | |
453 else | |
454 a = ao(data); | |
455 end | |
456 % Set name | |
457 a.name = aname; | |
458 % Set description | |
459 a.description = adescr; | |
460 % Set plotinfo | |
461 a.plotinfo = plotinfo; | |
462 % Add history | |
463 a.addHistory(getInfo('None'), pl, ao_invars, histin); | |
464 | |
465 %---------------------------------------------- | |
466 % set output | |
467 varargout{1} = a; | |
468 end | |
469 | |
470 %-------------------------------------------------------------------------- | |
471 % Get Info Object | |
472 %-------------------------------------------------------------------------- | |
473 function ii = getInfo(varargin) | |
474 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
475 sets = {}; | |
476 pl = []; | |
477 else | |
478 sets = {'Default'}; | |
479 pl = getDefaultPlist; | |
480 end | |
481 % Build info object | |
482 ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.helper, '$Id: join.m,v 1.60 2011/09/02 11:11:51 ingo Exp $', sets, pl); | |
483 ii.setArgsmin(2); | |
484 end | |
485 | |
486 %-------------------------------------------------------------------------- | |
487 % Get Default Plist | |
488 %-------------------------------------------------------------------------- | |
489 function plout = getDefaultPlist() | |
490 persistent pl; | |
491 if exist('pl', 'var')==0 || isempty(pl) | |
492 pl = buildplist(); | |
493 end | |
494 plout = pl; | |
495 end | |
496 | |
497 function pl = buildplist() | |
498 | |
499 pl = plist(); | |
500 | |
501 % Zero fill | |
502 p = param({'zerofill','Fills with zeros the gaps between the data points of the subsequent aos.'}, paramValue.YES_NO); | |
503 p.val.setValIndex(2); | |
504 pl.append(p); | |
505 | |
506 % Same T0 | |
507 p = param({'sameT0', ['Does not recalculate t0 but uses the common one.<br>', ... | |
508 'Note: the t0 among different objects must be the same!']}, paramValue.YES_NO); | |
509 p.val.setValIndex(2); | |
510 pl.append(p); | |
511 | |
512 % fstol | |
513 p = param({'fstol', ['Relative tolerance between sampling frequency of different objects.<br>', ... | |
514 'Jitter in the sampling frequency by less than this amount will be neglected.<br>', ... | |
515 'If the difference is more than the set value, an error will occur.']}, paramValue.DOUBLE_VALUE(1e-6)); | |
516 pl.append(p); | |
517 end | |
518 | |
519 | |
520 %-------------------------------------------------------------------------- | |
521 % Get Offset of this set of time-vectors | |
522 %-------------------------------------------------------------------------- | |
523 function Toff = getMinT0(as) | |
524 Toff = min(double(as.t0))*1e3; | |
525 end | |
526 |