comparison m-toolbox/classes/@ao/.#iplot.m.1.139 @ 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 % IPLOT provides an intelligent plotting tool for LTPDA.
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % DESCRIPTION: IPLOT provides an intelligent plotting tool for LTPDA.
5 %
6 % CALL: hfig = iplot (a,pl)
7 % [hfig, hax] = iplot (a,pl)
8 % [hfig, hax, hli] = iplot (a,pl)
9 %
10 % INPUTS: pl - a parameter list
11 % a - input analysis object
12 %
13 % OUTPUTS: hfig - handles to figures
14 % hax - handles to axes
15 % hli - handles to lines
16 %
17 % AO Plot Info
18 % ------------
19 %
20 % If an input AO has a filled plotinfo plist, then the options contained in
21 % therein will overide any other options. The recognised keys are:
22 %
23 % 'linestyle', 'linewidth', 'color', 'marker', 'legend_on'
24 %
25 % The possible values are all those accepted by plot.
26 %
27 %
28 % Notes on Parameters
29 % -------------------
30 %
31 % Many of the properties take cell-array values. If the length of
32 % the cell array is shorter than the number of lines to plot, the
33 % remaining lines will be plotted with the default options. If the
34 % cell array is of length 2 and the first cell contains the string
35 % 'all', then the second cell is used to set the propery of all
36 % lines.
37 %
38 %
39 % Error parameters: If you give more than one input AO then you must
40 % specify the following parameter values in a cell-array,
41 % one cell for each input AO. Leave the cell empty to
42 % plot no errors. Each error can be a value or a vector
43 % the same length as the data vector. If you give and
44 % upper limit but not lower limit, then the errors are
45 % assumed to be symmetric (and vice versa)
46 %
47 %
48 % EXAMPLES:
49 %
50 % 1) Plot two time-series AOs with different colors, line styles, and widths
51 %
52 % pl = plist('Linecolors', {'g', 'k'}, 'LineStyles', {'None', '--'}, 'LineWidths', {1, 4});
53 % iplot(tsao1, tsao2, pl);
54 %
55 % 2) Plot two time-series AOs in subplots. Also override the second legend
56 % text and the first line style.
57 %
58 % pl = plist('Arrangement', 'subplots', 'LineStyles', {'--'}, 'Legends', {'', 'My Sine Wave'});
59 % iplot(tsao1, tsao2, pl);
60 %
61 %
62 % 3) Plot two frequency-series AOs on subplots with the same Y-scales and
63 % Y-ranges
64 %
65 % pl1 = plist('Yscales', {'All', 'lin'});
66 % pl2 = plist('arrangement', 'subplots', 'YRanges', {'All', [1e-6 100]});
67 % iplot(fsd1, fsd2, pl1, pl2)
68 %
69 % <a href="matlab:utils.helper.displayMethodInfo('ao', 'iplot')">Parameters Description</a>
70 %
71 % VERSION: $Id: iplot.m,v 1.139 2011/06/01 13:08:47 hewitson Exp $
72 %
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74
75 % DEPRECATED xmaths and ymaths in release 2.4
76
77 % 3) Plot two time-series AOs taking the square of the y-values of the
78 % first AO and the log of the x-values of the second AO.
79 %
80 % pl = plist('Arrangement', 'subplots', 'YMaths', 'y.^2', 'XMaths', {'', 'log(x)'});
81 % iplot(tsao1, tsao2, pl);
82
83 % Math operations: You can specify rudimentary math operations to be
84 % performed on the X and Y data prior to plotting. The
85 % 'all' keyword is also supported by these parameters.
86 %
87
88
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 %
91 % TODO:
92 % 1) Add XRange, YRange, ZRange to xyzdata
93 %
94
95 function varargout = iplot(varargin)
96
97 import utils.const.*
98
99 %% Check if this is a call for parameters
100 if utils.helper.isinfocall(varargin{:})
101 varargout{1} = getInfo(varargin{3});
102 return
103 end
104
105 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename);
106
107 % Collect input variable names
108 in_names = cell(size(varargin));
109 for ii = 1:nargin,in_names{ii} = inputname(ii);end
110
111 % Collect all AOs and plists
112 [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names);
113 [upl, pl_invars] = utils.helper.collect_objects(varargin(:), 'plist', in_names);
114 if numel(upl)>1, upl = combine(upl); end
115
116 %% Go through AOs and collect them into similar types
117
118 tsAOs = [];
119 fsAOs = [];
120 xyAOs = [];
121 xyzAOs = [];
122 cAOs = [];
123
124 consistent = 1;
125 for jj = 1:numel(as)
126 % Check if AOs are consistent (all containing data of the same class):
127 if ~strcmpi(class(as(jj).data) , class(as(1).data) ), consistent = 0; end;
128 switch class(as(jj).data)
129 case 'tsdata'
130 if isempty(as(jj).y)
131 warning('AO %s has no data and will not be plotted', as(jj).name);
132 else
133 tsAOs = [tsAOs as(jj)]; %#ok<*AGROW>
134 end
135 case 'fsdata'
136 if isempty(as(jj).y)
137 warning('AO %s has no data and will not be plotted', as(jj).name);
138 else
139 fsAOs = [fsAOs as(jj)];
140 end
141 case 'xydata'
142 if isempty(as(jj).y)
143 warning('AO %s has no data and will not be plotted', as(jj).name);
144 else
145 xyAOs = [xyAOs as(jj)];
146 end
147 case 'xyzdata'
148 if isempty(as(jj).y)
149 warning('AO %s has no data and will not be plotted', as(jj).name); %#ok<*WNTAG>
150 else
151 xyzAOs = [xyzAOs as(jj)];
152 end
153 case 'cdata'
154 if isempty(as(jj).y)
155 warning('AO %s has no data and will not be plotted', as(jj).name);
156 else
157 cAOs = [cAOs as(jj)];
158 end
159 otherwise
160 warning('!!! Unknown data type %s', class(as(jj).data));
161 end
162 end
163
164
165 %% Now plot all the objects on separate figures
166 % (unless they're consistent and a figure handle was passed)
167
168 if consistent && ~isempty(upl), fig2plot = find(upl,'Figure'); else fig2plot = []; end
169
170 hfig = [];
171 hax = [];
172 hli = [];
173
174 %----------- TSDATA
175 if ~isempty(tsAOs)
176 % get default plist
177 dpl = getDefaultPlist('Time-series plot');
178 % combine the plists
179 pl = parse(upl, dpl);
180 % Call x-y plot
181 [hf, ha, hl] = xy_plot(tsAOs, pl, fig2plot);
182 hfig = [hfig hf];
183 hax = [hax ha];
184 hli = [hli hl];
185 end
186 %----------- XYDATA
187 if ~isempty(xyAOs)
188 % get default plist
189 dpl = getDefaultPlist('X-Y data plot');
190 % combine the plists
191 pl = parse(upl, dpl);
192 % Call x-y plot
193 [hf, ha, hl] = xy_plot(xyAOs, pl, fig2plot);
194 hfig = [hfig hf];
195 hax = [hax ha];
196 hli = [hli hl];
197 end
198 %----------- XYZDATA
199 if ~isempty(xyzAOs)
200 % get default plist
201 dpl = getDefaultPlist('3D plot');
202 % combine the plists
203 pl = parse(upl, dpl);
204 % Call x-y-z plot
205 [hf, ha, hl] = xyz_plot(xyzAOs, pl, fig2plot);
206 hfig = [hfig hf];
207 hax = [hax ha];
208 hli = [hli hl];
209 end
210 %----------- CDATA
211 if ~isempty(cAOs)
212 % get default plist
213 dpl = getDefaultPlist('Y data plot');
214 % combine the plists
215 pl = parse(upl, dpl);
216 % Call x-y plot
217 [hf, ha, hl] = y_plot(cAOs, pl, fig2plot);
218 hfig = [hfig hf];
219 hax = [hax ha];
220 hli = [hli hl];
221 end
222 %----------- FSDATA
223 if ~isempty(fsAOs)
224 % get default plist
225 dpl = getDefaultPlist('Frequency-series plot');
226 % combine the plists
227 pl = parse(upl, dpl);
228 % Call fsdata plot
229 [hf, ha, hl] = fs_plot(fsAOs, pl, fig2plot);
230 hfig = [hfig hf];
231 hax = [hax ha];
232 hli = [hli hl];
233 end
234
235 %% Deal with outputs
236 if nargout == 1
237 varargout{1} = hfig;
238 end
239 if nargout == 2
240 varargout{1} = hfig;
241 varargout{2} = hax;
242 end
243 if nargout == 3
244 varargout{1} = hfig;
245 varargout{2} = hax;
246 varargout{3} = hli;
247 end
248
249 if nargout > 3
250 error('### Incorrect number of outputs');
251 end
252
253 end
254
255 %--------------------------------------------------------------------------
256 % Plot fsdata objects
257 %
258 function varargout = fs_plot(varargin)
259
260 aos = varargin{1};
261 pl = varargin{2};
262 fig2plot = varargin{3};
263
264 UseLatex = find(pl, 'LatexLabels');
265 if ischar(UseLatex)
266 UseLatex = eval(UseLatex);
267 end
268
269 % Extract parameters
270 arrangement = find(pl, 'Arrangement');
271 colors = find(pl, 'Colors');
272 linecolors = find(pl, 'LineColors');
273 linestyles = find(pl, 'LineStyles');
274 markers = find(pl, 'Markers');
275 linewidths = find(pl, 'LineWidths');
276 legends = find(pl, 'Legends');
277 legendsFont = find(pl, 'LegendFontSize');
278 ylabels = find(pl, 'YLabels');
279 xlabels = find(pl, 'XLabels');
280 yscales = find(pl, 'YScales');
281 xscales = find(pl, 'XScales');
282 yranges = find(pl, 'YRanges');
283 xranges = find(pl, 'XRanges');
284 xmaths = find(pl, 'XMaths');
285 ymaths = find(pl, 'YMaths');
286 type = find(pl, 'Function');
287 legendLoc = find(pl, 'LegendLocation');
288 complexPlotType = find(pl, 'complexPlotType');
289 autoErrors = find(pl, 'AUTOERRORS');
290
291 % Convert the colour if it is a character to a cell-string
292 if ischar(colors)
293 colors = cellstr(colors);
294 end
295
296 % get errors
297 XerrL = find(pl, 'XerrL');
298 XerrU = find(pl, 'XerrU');
299 YerrL = find(pl, 'YerrL');
300 YerrU = find(pl, 'YerrU');
301 if ~iscell(XerrU), XerrU = {XerrU}; end
302 if ~iscell(XerrL), XerrL = {XerrL}; end
303 if ~iscell(YerrU), YerrU = {YerrU}; end
304 if ~iscell(YerrL), YerrL = {YerrL}; end
305 if (numel(XerrL) > 1 && numel(XerrL) ~= numel(aos)) || ...
306 (numel(YerrL) > 1 && numel(YerrL) ~= numel(aos)) || ...
307 (numel(XerrU) > 1 && numel(XerrU) ~= numel(aos)) || ...
308 (numel(YerrU) > 1 && numel(YerrU) ~= numel(aos))
309 error('### Please specify 1 set of errors for all AOs, or a set of errors for each AO.');
310 end
311
312 % check whether we want legends or not
313 if iscell(legends)
314 legendsOn = 1;
315 else
316 if strcmpi(legends, 'off')
317 legendsOn = 0;
318 else
319 legendsOn = 1;
320 legends = [];
321 end
322 end
323
324 if ~isempty(ymaths) || ~isempty(xmaths)
325 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
326 end
327
328 if ~iscell(linewidths), linewidths = {linewidths}; end
329 if ~iscell(linestyles), linestyles = {linestyles}; end
330 if ~iscell(linecolors), linecolors = {linecolors}; end
331 if ~iscell(markers), markers = {markers}; end
332 if ~iscell(legends), legends = {legends}; end
333 if ~iscell(ylabels), ylabels = {ylabels}; end
334 if ~iscell(xlabels), xlabels = {xlabels}; end
335 if ~iscell(xmaths), xmaths = {xmaths}; end
336 if ~iscell(ymaths), ymaths = {ymaths}; end
337 if ~iscell(xscales), xscales = {xscales}; end
338 if ~iscell(yscales), yscales = {yscales}; end
339 if ~iscell(xranges), xranges = {xranges}; end
340 if ~iscell(yranges), yranges = {yranges}; end
341
342 % collect figure handles
343 fsfig = []; fsax = []; fsli = [];
344 % Legend holder
345 legendStrR = [];
346 legendStrI = [];
347 % Helper variables
348 ymin = Inf;
349 ymax = -Inf;
350 xmin = Inf;
351 xmax = -Inf;
352 complexFig = [];
353 complexAxes = [];
354
355 if ~isempty(aos)
356 % Now loop over AOs
357 Na = length(aos);
358 % First to check if any are complex y data including any Y maths at the same
359 % time.
360 haveComplex = 0;
361 for jj = 1:Na
362 % Get data
363 y = aos(jj).data.getY;
364 % Do any math operations
365 ymath = parseOptions(jj, ymaths, 'y');
366 eval(sprintf('y = %s;', ymath));
367 % Is this a complex plot?
368 if ~isreal(y)
369 haveComplex = 1;
370 end
371 end
372
373 % Do we want to use a unit placeholder on the yaxis?
374 yunits = aos(1).data.yunits;
375 yunitPlaceholder = '[Mixed]';
376 useYunitPlaceholder = false;
377 if strcmpi(arrangement, 'stacked')
378 for jj = 1:Na
379 if yunits ~= aos(jj).data.yunits
380 useYunitPlaceholder = true;
381 break;
382 end
383 end
384 end
385 ylabeli = '';
386 % Do we want to use a unit placeholder on the xaxis?
387 xunits = aos(1).data.xunits;
388 xunitPlaceholder = '[Mixed]';
389 useXunitPlaceholder = false;
390 if strcmpi(arrangement, 'stacked')
391 for jj = 1:Na
392 if xunits ~= aos(jj).data.xunits
393 useXunitPlaceholder = true;
394 break;
395 end
396 end
397 end
398
399 % No plot
400 for jj = 1:Na
401
402 if useYunitPlaceholder
403 yunits = yunitPlaceholder;
404 else
405 yunits = aos(jj).data.yunits;
406 end
407 if useXunitPlaceholder
408 xunits = xunitPlaceholder;
409 else
410 xunits = aos(jj).data.xunits;
411 end
412 % set real and imag subplot handles to empty
413 fsax_r = [];
414 fsax_i = [];
415 % Get data
416 x = aos(jj).data.getX; y = aos(jj).data.getY;
417 % Do any math operations
418 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
419 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
420 % what figures do we need?
421 switch arrangement
422 case 'single'
423 fsfig = [fsfig figure];
424 col = colors{1};
425 % check if this data set is real or complex
426 if ~isreal(y)
427 % complex means we use two subplots
428 fsax_r = subplot(2,1,1); fsax_i = subplot(2,1,2);
429 fsax = [fsax fsax_r fsax_i];
430 complexFig = [complexFig get(fsax_r, 'Parent')];
431 complexAxes = [complexAxes fsax_r fsax_i];
432 else
433 % real means we use a single subplot
434 fsax_r = subplot(1, 1, 1);
435 fsax = [fsax fsax_r];
436 end
437 % Make sure we reset the helper variables in this case
438 ymin = Inf; ymax = -Inf; xmin = Inf; xmax = -Inf;
439 case 'stacked'
440 if ~isempty(fig2plot), fsfig = fig2plot;
441 elseif jj == 1, fsfig = figure;
442 end
443 % if at least one of the input fsdata AOs is complex, we need to
444 % allow for subplots
445 if haveComplex
446 fsax_r = subplot(2,1,1,'Parent',fsfig); fsax_i = subplot(2,1,2,'Parent',fsfig);
447 fsax = [fsax_r fsax_i];
448 if jj == 1
449 complexFig = [complexFig fsfig];
450 complexAxes = [complexAxes fsax_r fsax_i];
451 end
452 else
453 fsax_r = subplot(1, 1, 1,'Parent',fsfig);
454 fsax = fsax_r;
455 end
456 col = colors{mod(jj-1,length(colors))+1};
457 hold(fsax_r, 'on');
458 if ishandle(fsax_i)
459 hold(fsax_i, 'on');
460 end
461 case 'subplots'
462 if ~isempty(fig2plot), fsfig = fig2plot;
463 elseif jj == 1, fsfig = figure;
464 end
465 c = 1+(jj-1)*2;
466 sx = Na;
467 sy = 2;
468 % Now we have one or two subplots per input object.
469 if ~isreal(y)
470 fsax_r = subplot(sx, sy,c); fsax_i = subplot(sx, sy,c+1);
471 fsax = [fsax fsax_r fsax_i];
472 else
473 fsax_r = subplot(sx, sy, c:c+1);
474 fsax = [fsax fsax_r];
475 end
476 col = colors{1};
477 % Make sure we reset the helper variables in this case
478 ymin = Inf; ymax = -Inf; xmin = Inf; xmax = -Inf;
479 otherwise
480 error('### Unknown plot arrangement');
481 end
482
483 % Process errors
484 [fcn, xu, xl, yu, yl] = process_errors(jj, size(y), type, XerrU, XerrL, YerrU, YerrL, aos(jj), autoErrors);
485
486 %------- Plot the data
487
488 % plot real or complex data and setup default values for scale and
489 % labels as we go.
490 if isreal(y)
491 % if the data are real, then we don't expect negative error bars
492 idx = find(yl>abs(y));
493 yl(idx) = 0.999*abs(y(idx));
494 switch fcn
495 case 'errorbar'
496 li = errorbar(fsax_r, x, y, yl, yu);
497 le = false;
498 case type
499 li = feval(type, fsax_r, x, y);
500 le = false; % we have no error plots
501 case 'errorbarxy'
502 lhs = errorbarxy(fsax_r, x, y, xu, yu, xl, yl);
503 li = lhs(1);
504 le = lhs(2);
505 end
506 fsli = [fsli li];
507 ylabelr = ''; ylabeli = 'imag';
508 yscaleR = 'log'; yscaleI = 'lin';
509 xscaleR = 'log'; xscaleI = 'log';
510 else
511 switch complexPlotType
512 case 'realimag'
513 switch fcn
514 case 'errorbar'
515 ry = real(y);
516 ferr = yl./abs(y);
517 yl = ry.*ferr;
518 yu = ry.*ferr;
519 li = errorbar(fsax_r, x, ry, yl, yu);
520 le = false;
521 case type
522 li = feval(type, fsax_r, x, real(y));
523 le = false; % we have no error plots
524 case 'errorbarxy'
525 lhs = errorbarxy(fsax_r, x, real(y), xu, yu, xl, yl);
526 li = lhs(1);
527 le = lhs(2);
528 end
529 switch fcn
530 case 'errorbar'
531 iy = imag(y);
532 ferr = yl./abs(y);
533 yl = iy.*ferr;
534 yu = iy.*ferr;
535 li = [li errorbar(fsax_i, x, iy, yl, yu)];
536 le = false;
537 case type
538 li = [li feval(type, fsax_i, x, imag(y))];
539 le = false; % we have no error plots
540 case 'errorbarxy'
541 lhs = errorbarxy(fsax_i, x, imag(y), xu, yu, xl, yl);
542 li = [li lhs(1)];
543 le = lhs(2);
544 end
545 fsli = [fsli li];
546 ylabelr = 'real'; ylabeli = 'imag';
547 yscaleR = 'lin'; yscaleI = 'lin';
548 xscaleR = 'log'; xscaleI = 'log';
549 case 'absdeg'
550 a = abs(y);
551 p = utils.math.phase(y);
552 % if the data are absolute values, then we don't expect
553 % negative error bars
554 idx = find(yl>abs(y));
555 yl(idx) = 0.999*abs(y(idx));
556 switch fcn
557 case 'errorbar'
558 li = errorbar(fsax_r, x, a, yl, yu);
559 le = false;
560 case type
561 li = feval(type, fsax_r, x, abs(y));
562 le = false; % we have no error plots
563 case 'errorbarxy'
564 lhs = errorbarxy(fsax_r, x, abs(y), xu, yu, xl, yl);
565 li = lhs(1); le = lhs(2);
566 end
567 switch fcn
568 case 'errorbar'
569 ferr = yl./a;
570 yl = 360.*ferr;
571 yu = 360.*ferr;
572 li = [li errorbar(fsax_i, x, p, yl, yu)];
573 le = false;
574 case type
575 li = [li feval(type, fsax_i, x, utils.math.phase(y))];
576 le = false; % we have no error plots
577 case 'errorbarxy'
578 lhs = errorbarxy(fsax_i, x, utils.math.phase(y), xu, yu, xl, yl);
579 li = [li lhs(1)]; le = lhs(2);
580 end
581 fsli = [fsli li];
582 ylabelr = 'Amplitude'; ylabeli = 'Phase';
583 yscaleR = 'log'; yscaleI = 'lin';
584 xscaleR = 'log'; xscaleI = 'log';
585 case 'absrad'
586 % if the data are absolute values, then we don't expect
587 % negative error bars
588 idx = find(yl>abs(y));
589 yl(idx) = 0.999*abs(y(idx));
590 switch fcn
591 case 'errorbar'
592 li = errorbar(fsax_r, x, abs(y), yl, yu);
593 le = false; %#ok<*NASGU>
594 case type
595 li = feval(type, fsax_r, x, abs(y));
596 le = false; % we have no error plots
597 case 'errorbarxy'
598 lhs = errorbarxy(fsax_r, x, abs(y), xu, yu, xl, yl);
599 li = lhs(1); le = lhs(2);
600 end
601 switch fcn
602 case 'errorbar'
603 ferr = yl./abs(y);
604 yl = pi.*ferr;
605 yu = pi.*ferr;
606 li = [li errorbar(fsax_i, x, angle(y), yl, yu)];
607 le = false;
608 case type
609 li = [li feval(type, fsax_i, x, angle(y))];
610 le = false; % we have no error plots
611 case 'errorbarxy'
612 lhs = errorbarxy(fsax_i, x, angle(y), xu, yu, xl, yl);
613 li = [li lhs(1)];
614 le = lhs(2);
615 end
616 fsli = [fsli li];
617 ylabelr = 'Amplitude'; ylabeli = 'Phase';
618 yscaleR = 'log'; yscaleI = 'lin';
619 xscaleR = 'log'; xscaleI = 'log';
620 otherwise
621 error('### Unknown plot type for complex data');
622 end
623 end
624
625 %------- Axis properties
626 % axis counter
627 c = 1+(jj-1)*2;
628
629 % Set real axis ylabel
630 ylstrR = parseOptions(c, ylabels, ylabelr);
631 ylstrR = prepareAxisLabel(yunits, ymath, ylstrR, 'y', UseLatex);
632 ylstrR = fixlabel(ylstrR);
633 if UseLatex
634 ylabel(fsax_r, ylstrR, 'interpreter', 'latex');
635 else
636 ylabel(fsax_r, ylstrR);
637 end
638
639 % Set imag axis ylabel
640 if ishandle(fsax_i)
641 ylstrI = parseOptions(c+1, ylabels, ylabeli);
642 switch complexPlotType
643 case 'realimag'
644 ylstrI = prepareAxisLabel(yunits, ymath, ylstrI, 'y', UseLatex);
645 case 'absdeg'
646 ylstrI = prepareAxisLabel(unit('deg'), [], ylstrI, 'y', UseLatex);
647 case 'absrad'
648 ylstrI = prepareAxisLabel(unit('rad'), [], ylstrI, 'y', UseLatex);
649 otherwise
650 end
651 ylstrI = fixlabel(ylstrI);
652 if UseLatex
653 ylabel(fsax_i, ylstrI, 'interpreter', 'latex');
654 else
655 ylabel(fsax_i, ylstrI);
656 end
657 end
658
659 % Set xlabel
660 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
661 xlstr = prepareAxisLabel(xunits, xmath, xlstr, 'x', UseLatex);
662 xlstr = fixlabel(xlstr);
663 if isreal(y)
664 if UseLatex
665 xlabel(fsax_r, xlstr, 'interpreter', 'latex');
666 else
667 xlabel(fsax_r, xlstr);
668 end
669 else
670 % Do not draw Xlabel and XTicklabel on the real plot
671 set(fsax_r, 'XTickLabel',[]);
672 end
673 if ~isempty(fsax_i) && ishandle(fsax_i)
674 if UseLatex
675 xlabel(fsax_i, xlstr, 'interpreter', 'latex');
676 else
677 xlabel(fsax_i, xlstr);
678 end
679 end
680
681 % Set grid on or off
682 grid(fsax_r, 'on');
683 if ~isempty(fsax_i) && ishandle(fsax_i), grid(fsax_i, 'on'); end
684
685 % Set Y scale
686 yscaleR = parseOptions(c, yscales, yscaleR);
687 yscaleI = parseOptions(c+1, yscales, yscaleI);
688 set(fsax_r, 'YScale', yscaleR);
689 if ~isempty(fsax_i) && ishandle(fsax_i), set(fsax_i, 'YScale', yscaleI); end
690
691 % Set X scale
692 xscaleR = parseOptions(c, xscales, xscaleR);
693 xscaleI = parseOptions(c+1, xscales, xscaleI);
694 set(fsax_r, 'XScale', xscaleR);
695 if ~isempty(fsax_i) && ishandle(fsax_i)
696 set(fsax_i, 'XScale', xscaleI);
697 end
698
699 % Set Y range
700 yrange = parseOptions(c, yranges, []);
701 if ~isempty(yrange)
702 set(fsax_r, 'YLim', yrange);
703 elseif strcmpi(yscaleR, 'log')
704 [tcks,ymin,ymax] = getRealYDataTicks(y, ymin, ymax, complexPlotType, yscaleR);
705 nticks = numel(tcks);
706 if nticks>0 && nticks < 10
707 yrange = [tcks(1) tcks(end)];
708 set(fsax_r, 'YLim', yrange);
709 set(fsax_r, 'Ytickmode', 'manual');
710 set(fsax_r, 'Ytick', tcks);
711 end
712 end
713 yrange = parseOptions(c+1, yranges, []);
714 if ~isempty(fsax_i) && ishandle(fsax_i)
715 if ~isempty(yrange)
716 set(fsax_i, 'YLim', yrange);
717 elseif strcmpi(yscaleI, 'log')
718
719 % This doesn't really make sense since the imaginary part or
720 % phase or angle will always contain negative parts. Would the
721 % user really choose a log scale in that case?
722 % tcks = getImagYDataTicks(y, ymin, ymax, complexPlotType, yscaleI);
723 % if ~isempty(tcks)
724 % yrange = [tcks(1) tcks(end)];
725 % set(fsax_i, 'YLim', yrange);
726 % set(fsax_i, 'Ytickmode', 'manual');
727 % set(fsax_i, 'Ytick', tcks);
728 % end
729 end
730 end
731
732 % Set X range
733 xrange = parseOptions(c, xranges, []);
734 if ~isempty(xrange)
735 set(fsax_r, 'XLim', xrange);
736 elseif strcmpi(xscaleR, 'log')
737 xmin = min(xmin, floor(log10(min(x(x>0)))));
738 xmax = max(xmax, ceil(log10(max(x(x>0)))));
739 tcks = logspace(xmin, xmax, xmax - xmin +1);
740 xrange = [tcks(1) tcks(end)];
741 set(fsax_r, 'XLim', xrange);
742 set(fsax_r, 'Xtickmode', 'manual');
743 set(fsax_r, 'Xtick', tcks);
744 end
745 xrange = parseOptions(c+1, xranges, []);
746 if ~isempty(fsax_i) && ishandle(fsax_i)
747 if ~isempty(xrange)
748 set(fsax_i, 'XLim', xrange);
749 elseif strcmpi(xscaleR, 'log')
750 xmin = min(xmin, floor(log10(min(x(x>0)))));
751 xmax = max(xmax, ceil(log10(max(x(x>0)))));
752 tcks = logspace(xmin, xmax, xmax - xmin +1);
753 xrange = [tcks(1) tcks(end)];
754 set(fsax_i, 'XLim', xrange);
755 set(fsax_i, 'Xtickmode', 'manual');
756 set(fsax_i, 'Xtick', tcks);
757 end
758 end
759
760 %------- line properties
761 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
762 linecolors, col, ...
763 linestyles, '-', ...
764 linewidths, get(0,'DefaultLineLineWidth'), ...
765 markers, 'None');
766
767 % set props
768 set(li, 'Color', col);
769 set(li, 'LineStyle', lstyle);
770 set(li, 'LineWidth', lwidth);
771 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
772 mkr = '.';
773 end
774 set(li, 'Marker', mkr);
775
776 % Set legend string
777 if legendsOn
778 if ~isempty(aos(jj).plotinfo) && ...
779 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
780 ~aos(jj).plotinfo.find('LEGEND_ON')
781 for kk=1:numel(li)
782 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
783 end
784 else
785 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
786 legendStrR = [legendStrR cellstr(lstr)];
787 if ~isreal(y)
788 legendStrI = [legendStrI cellstr(lstr)];
789 end
790 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
791 legend(fsax_r, fixlabel(legendStrR{end}), 'Location', legendLoc);
792 if ~isempty(fsax_i) && ishandle(fsax_i)
793 h = legend(fsax_i, fixlabel(legendStrI), 'Location', legendLoc);
794 end
795 end
796 end
797 end
798
799 end % End loop over AOs
800
801 % Make sure the plots are refreshed
802 drawnow();
803 % Trim the size of complex plots
804 for jj = 1:length(complexFig)
805 p_r = get(complexAxes(2*jj-1), 'Position');
806 p_i = get(complexAxes(2*jj), 'Position');
807 dh = (p_r(2) - (p_i(2)+p_i(4)))/3;
808 set(complexAxes(2*jj-1), 'Position', [p_r(1) p_r(2)-dh p_r(3) p_r(4)+dh]);
809 set(complexAxes(2*jj), 'Position', [p_i(1) p_i(2) p_i(3) p_i(4)+dh]);
810 end
811
812 % Process legends for stacked plots
813 if legendsOn
814 if strcmp(arrangement, 'stacked')
815 if ~isempty(legendStrR)
816 h = legend(fsax_r, fixlabel(legendStrR), 'Location', legendLoc);
817 set(h, 'FontSize', legendsFont);
818 if ~isempty(fsax_i) && ishandle(fsax_i)
819 h = legend(fsax_i, fixlabel(legendStrI), 'Location', legendLoc);
820 set(h, 'FontSize', legendsFont);
821 end
822 end
823 end
824 end
825 end % End ~isempty AOs
826
827 % Apply plot settings to the figure
828 applyPlotSettings(fsax, fsli);
829
830 % Set outputs
831 if nargout > 0
832 varargout{1} = fsfig;
833 end
834 if nargout > 1
835 varargout{2} = fsax;
836 end
837 if nargout == 3
838 varargout{3} = fsli;
839 end
840 if nargout > 3
841 error('### Too many output arguments');
842 end
843 end % End fs_plot
844
845 %--------------------------------------------------------------------------
846 % Plot tsdata and xydata objects
847 %
848 function varargout = xy_plot(varargin)
849
850 aos = varargin{1};
851 pl = varargin{2};
852 fig2plot = varargin{3};
853 Na = length(aos);
854
855 UseLatex = find(pl, 'LatexLabels');
856 if ischar(UseLatex)
857 UseLatex = eval(UseLatex);
858 end
859
860 % Extract parameters
861 arrangement = find(pl, 'Arrangement');
862 linecolors = find(pl, 'LineColors');
863 colors = find(pl, 'Colors');
864 linestyles = find(pl, 'LineStyles');
865 markers = find(pl, 'Markers');
866 linewidths = find(pl, 'LineWidths');
867 legends = find(pl, 'Legends');
868 legendsFont = find(pl, 'LegendFontSize');
869 ylabels = find(pl, 'YLabels');
870 xlabels = find(pl, 'XLabels');
871 xmaths = find(pl, 'XMaths');
872 ymaths = find(pl, 'YMaths');
873 yranges = find(pl, 'YRanges');
874 xranges = find(pl, 'XRanges');
875 yscales = find(pl, 'YScales');
876 xscales = find(pl, 'XScales');
877 type = find(pl, 'Function');
878 legendLoc = find(pl, 'LegendLocation');
879 xunits = find(pl, 'Xunits');
880 autoErrors = utils.prog.yes2true(find(pl, 'AUTOERRORS'));
881
882 % Convert the colour if it is a character to a cell-string
883 if ischar(colors)
884 colors = cellstr(colors);
885 end
886
887 % get errors
888 XerrL = find(pl, 'XerrL');
889 XerrU = find(pl, 'XerrU');
890 YerrL = find(pl, 'YerrL');
891 YerrU = find(pl, 'YerrU');
892 if ~iscell(XerrU), XerrU = {XerrU}; end
893 if ~iscell(XerrL), XerrL = {XerrL}; end
894 if ~iscell(YerrU), YerrU = {YerrU}; end
895 if ~iscell(YerrL), YerrL = {YerrL}; end
896 if (numel(XerrL) > 1 && numel(XerrL) ~= numel(aos)) || ...
897 (numel(YerrL) > 1 && numel(YerrL) ~= numel(aos)) || ...
898 (numel(XerrU) > 1 && numel(XerrU) ~= numel(aos)) || ...
899 (numel(YerrU) > 1 && numel(YerrU) ~= numel(aos))
900 error('### Please specify 1 set of errors for all AOs, or a set of errors for each AO.');
901 end
902
903 torigin = [];
904
905 % check whether we want legends or not
906 if iscell(legends)
907 legendsOn = 1;
908 else
909 if strcmpi(legends, 'off')
910 legendsOn = 0;
911 else
912 legendsOn = 1;
913 legends = [];
914 end
915 end
916
917 if ~isempty(ymaths) || ~isempty(xmaths)
918 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
919 end
920
921 if ~iscell(linewidths), linewidths = {linewidths}; end
922 if ~iscell(linestyles), linestyles = {linestyles}; end
923 if ~iscell(linecolors), linecolors = {linecolors}; end
924 if ~iscell(markers), markers = {markers}; end
925 if ~iscell(legends), legends = {legends}; end
926 if ~iscell(ylabels), ylabels = {ylabels}; end
927 if ~iscell(xlabels), xlabels = {xlabels}; end
928 if ~iscell(xmaths), xmaths = {xmaths}; end
929 if ~iscell(ymaths), ymaths = {ymaths}; end
930 if ~iscell(xranges), xranges = {xranges}; end
931 if ~iscell(yranges), yranges = {yranges}; end
932 if ~iscell(xscales), xscales = {xscales}; end
933 if ~iscell(yscales), yscales = {yscales}; end
934 if ~iscell(xunits), xunits = {xunits}; end
935
936 % collect figure handles
937 tsfig = []; tsax = []; tsli = [];
938 % Legend holder
939 legendStr = [];
940 if ~isempty(aos)
941 % Now loop over AOs to get earliest start time
942 T0 = 0;
943 if strcmp(arrangement, 'stacked')
944 T0 = 1e50;
945 for jj = 1:Na
946 % Get this AO
947 if isa(aos(jj).data, 'tsdata') && aos(jj).data.t0.utc_epoch_milli/1000 < T0
948 T0 = floor(aos(jj).data.t0.utc_epoch_milli/1000);
949 end
950 end
951 end
952
953 % Do we want to use a unit placeholder on the yaxis?
954 yunits = aos(1).data.yunits;
955 yunitPlaceholder = '[Mixed]';
956 useYunitPlaceholder = false;
957 if strcmpi(arrangement, 'stacked')
958 for jj = 1:Na
959 if yunits ~= aos(jj).data.yunits
960 useYunitPlaceholder = true;
961 break;
962 end
963 end
964 end
965
966 % Do we want to use a unit placeholder on the xaxis?
967 firstXunits = aos(1).data.xunits;
968 xunitPlaceholder = '[Mixed]';
969 useXunitPlaceholder = false;
970 if strcmpi(arrangement, 'stacked')
971 for jj = 1:Na
972 if firstXunits ~= aos(jj).data.xunits
973 useXunitPlaceholder = true;
974 break;
975 end
976 end
977 end
978
979 % Now loop over AOs
980 for jj = 1:Na
981 % Get this AO
982 toff = 0;
983
984 if useYunitPlaceholder
985 yunits = yunitPlaceholder;
986 else
987 yunits = aos(jj).data.yunits;
988 end
989
990 % what figures do we need?
991 switch arrangement
992 case 'single'
993 tsfig = [tsfig figure];
994 tsax = subplot(1,1,1);
995 col = colors{1};
996 if isa(aos(jj).data, 'tsdata')
997 torigin = aos(jj).data.t0;
998 end
999 case 'stacked'
1000 if ~isempty(fig2plot), tsfig = fig2plot;
1001 elseif jj==1, tsfig = figure;
1002 end
1003 tsax = subplot(1,1,1,'Parent',tsfig);
1004 col = colors{mod(jj-1,length(colors))+1};
1005 hold on;
1006 % deal with time-stamps here
1007 if isa(aos(jj).data, 'tsdata')
1008 toff = aos(jj).data.t0.utc_epoch_milli/1000 - T0;
1009 else
1010 toff = 0;
1011 end
1012 if isa(aos(jj).data, 'tsdata')
1013 torigin = time(T0);
1014 end
1015 case 'subplots'
1016 if ~isempty(fig2plot), tsfig = fig2plot;
1017 elseif jj==1, tsfig = figure;
1018 end
1019 tsax = [tsax subplot(Na, 1, jj,'Parent',tsfig)];
1020 col = colors{1};
1021 if isa(aos(jj).data, 'tsdata')
1022 torigin = aos(jj).data.t0;
1023 end
1024 otherwise
1025 error('### Unknown plot arrangement');
1026 end
1027
1028 %------- Apply math functions
1029
1030 % Get data and add t0 offset for this time-series
1031 x = aos(jj).data.getX + toff;
1032 y = aos(jj).data.getY;
1033
1034 % Apply any math operations
1035 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1036 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1037
1038 % Process X units
1039 if useXunitPlaceholder
1040 xunit = xunitPlaceholder;
1041 dateTicSpec = false;
1042 else
1043 if isa(aos(jj).data, 'tsdata')
1044 xunitIn = char(aos(jj).data.xunits);
1045 xunit = parseOptions(jj, xunits, xunitIn);
1046 [x, xunit, dateTicSpec] = convertXunits(x, torigin, xunit, xunitIn);
1047 elseif isa(aos(jj).data, 'xydata')
1048 xunitIn = char(aos(jj).data.xunits);
1049 xunit = parseOptions(jj, xunits, xunitIn);
1050 dateTicSpec = false;
1051 else
1052 xunit = '';
1053 dateTicSpec = false;
1054 end
1055 end
1056
1057 % Process errors
1058 [fcn, xu, xl, yu, yl] = process_errors(jj, size(y), type, XerrU, XerrL, YerrU, YerrL, aos(jj), autoErrors);
1059
1060 %------- Plot the data
1061
1062 switch fcn
1063 case 'errorbar'
1064 li = errorbar(tsax(end), x, y, yl, yu);
1065 le = false;
1066 case type
1067 li = feval(type, tsax(end), x, y);
1068 le = false; % we have no error plots
1069 case 'errorbarxy'
1070 lhs = errorbarxy(tsax(end), x, y, xu, yu, xl, yl);
1071 li = lhs(1);
1072 le = lhs(2);
1073 end
1074 tsli = [tsli li];
1075 if isa(aos(jj).data, 'tsdata')
1076 title(sprintf('Time origin: %s', char(torigin)));
1077 end
1078
1079 %------- Add time origin to the axis handle
1080
1081 if isempty(torigin)
1082 torigin = time();
1083 end
1084
1085 set(tsax(end), 'UserData', torigin)
1086 try
1087 dcm_obj = datacursormode(get(tsfig(end),'Parent'));
1088 catch
1089 dcm_obj = datacursormode(tsfig(end));
1090 end
1091 set(dcm_obj, 'UpdateFcn', @utils.plottools.datacursormode)
1092
1093 %---------- Call datetic
1094 if dateTicSpec
1095 datetick(tsax(end), 'x', xunit(2:end-1), 'keeplimits');
1096 end
1097
1098 %------- Axis properties
1099
1100 % Set ylabel
1101 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1102 ylstr = prepareAxisLabel(yunits, ymath, ylstr, 'y', UseLatex);
1103 ylstr = fixlabel(ylstr);
1104 if UseLatex
1105 ylabel(ylstr, 'interpreter', 'latex');
1106 else
1107 ylabel(ylstr);
1108 end
1109
1110 % Set xlabel
1111 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1112 xlstr = prepareAxisLabel(xunit, xmath, xlstr, 'x', UseLatex);
1113 xlstr = fixlabel(xlstr);
1114 if UseLatex
1115 xlabel(xlstr, 'interpreter', 'latex');
1116 else
1117 xlabel(xlstr);
1118 end
1119
1120 % Set Y range
1121 yrange = parseOptions(jj, yranges, []);
1122 if ~isempty(yrange), set(tsax(end), 'YLim', yrange); end
1123
1124 % Set X range
1125 xrange = parseOptions(jj, xranges, []);
1126 if ~isempty(xrange), set(tsax(end), 'XLim', xrange); end
1127
1128 % Set Y scale
1129 yscale = parseOptions(jj, yscales, 'lin');
1130 set(tsax(end), 'YScale', yscale);
1131
1132 % Set X scale
1133 xscale = parseOptions(jj, xscales, 'lin');
1134 set(tsax(end), 'XScale', xscale);
1135
1136 % Set grid on or off
1137 grid(tsax(end), 'on');
1138
1139
1140 %------- line properties
1141 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
1142 linecolors, col, ...
1143 linestyles, '-', ...
1144 linewidths, get(0,'DefaultLineLineWidth'), ...
1145 markers, 'None');
1146
1147
1148 % Set line color
1149 set(li, 'Color', col);
1150 if ~isempty(le) && ishandle(le), set(le, 'Color', col); end
1151 % Set line style
1152 set(li, 'LineStyle', lstyle);
1153 if ishandle(le), set(le, 'LineStyle', lstyle); end
1154 % Set markers
1155 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
1156 mkr = '.';
1157 end
1158 set(li, 'Marker', mkr);
1159 % Set line widths
1160 set(li, 'LineWidth', lwidth);
1161 if ~isempty(le) && ishandle(le), set(le, 'LineWidth', lwidth); end
1162
1163 % Set legend string
1164 if legendsOn
1165 if ~isempty(aos(jj).plotinfo) && ...
1166 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1167 ~aos(jj).plotinfo.find('LEGEND_ON')
1168 for kk=1:numel(li)
1169 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1170 end
1171 else
1172 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1173 legendStr = [legendStr cellstr(lstr)];
1174 % Set the legend now if we can
1175 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
1176 legend(fixlabel(legendStr{end}), 'Location', legendLoc);
1177 end
1178 end
1179 end
1180 end
1181
1182 % Process legends for stacked plots
1183 if legendsOn
1184 if strcmp(arrangement, 'stacked')
1185 if ~isempty(legendStr)
1186 h = legend(fixlabel(legendStr), 'Location', legendLoc);
1187 set(h, 'FontSize', legendsFont);
1188 end
1189 end
1190 end
1191 end % End if empty AOs
1192
1193 % Apply plot settings to the figure
1194 applyPlotSettings(tsax, tsli);
1195
1196 % Set outputs
1197 if nargout > 0
1198 varargout{1} = tsfig;
1199 end
1200 if nargout > 1
1201 varargout{2} = tsax;
1202 end
1203 if nargout == 3
1204 varargout{3} = tsli;
1205 end
1206 if nargout > 3
1207 error('### Too many output arguments');
1208 end
1209 end % end xy_plot
1210
1211
1212 %--------------------------------------------------------------------------
1213 % Plot cdata objects
1214 %
1215 function varargout = y_plot(varargin)
1216
1217 aos = varargin{1};
1218 pl = varargin{2};
1219 fig2plot = varargin{3};
1220
1221 UseLatex = find(pl, 'LatexLabels');
1222 if ischar(UseLatex)
1223 UseLatex = eval(UseLatex);
1224 end
1225
1226 % Extract parameters
1227 arrangement = find(pl, 'Arrangement');
1228 linecolors = find(pl, 'LineColors');
1229 colors = find(pl, 'Colors');
1230 linestyles = find(pl, 'LineStyles');
1231 markers = find(pl, 'Markers');
1232 linewidths = find(pl, 'LineWidths');
1233 legends = find(pl, 'Legends');
1234 legendsFont = find(pl, 'LegendFontSize');
1235 ylabels = find(pl, 'YLabels');
1236 xlabels = find(pl, 'XLabels');
1237 xmaths = find(pl, 'XMaths');
1238 ymaths = find(pl, 'YMaths');
1239 yranges = find(pl, 'YRanges');
1240 xranges = find(pl, 'XRanges');
1241 yscales = find(pl, 'YScales');
1242 xscales = find(pl, 'XScales');
1243 type = find(pl, 'Function');
1244 legendLoc = find(pl, 'LegendLocation');
1245 autoErrors = find(pl, 'AUTOERRORS');
1246
1247 % Convert the colour if it is a character to a cell-string
1248 if ischar(colors)
1249 colors = cellstr(colors);
1250 end
1251
1252 % get errors
1253 YerrL = find(pl, 'YerrL');
1254 YerrU = find(pl, 'YerrU');
1255 if ~iscell(YerrU), YerrU = {YerrU}; end
1256 if ~iscell(YerrL), YerrL = {YerrL}; end
1257 if (numel(YerrL) > 1 && numel(YerrL) ~= numel(aos)) || ...
1258 (numel(YerrU) > 1 && numel(YerrU) ~= numel(aos))
1259 error('### Please specify 1 set of errors for all AOs, or a set of errors for each AO.');
1260 end
1261
1262 % check whether we want legends or not
1263 if iscell(legends)
1264 legendsOn = 1;
1265 else
1266 if strcmp(legends, 'off')
1267 legendsOn = 0;
1268 else
1269 legendsOn = 1;
1270 legends = [];
1271 end
1272 end
1273
1274 if ~isempty(ymaths) || ~isempty(xmaths)
1275 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
1276 end
1277
1278 if ~iscell(linewidths), linewidths = {linewidths}; end
1279 if ~iscell(linestyles), linestyles = {linestyles}; end
1280 if ~iscell(linecolors), linecolors = {linecolors}; end
1281 if ~iscell(markers), markers = {markers}; end
1282 if ~iscell(legends), legends = {legends}; end
1283 if ~iscell(ylabels), ylabels = {ylabels}; end
1284 if ~iscell(xlabels), xlabels = {xlabels}; end
1285 if ~iscell(xmaths), xmaths = {xmaths}; end
1286 if ~iscell(ymaths), ymaths = {ymaths}; end
1287 if ~iscell(xranges), xranges = {xranges}; end
1288 if ~iscell(yranges), yranges = {yranges}; end
1289 if ~iscell(xscales), xscales = {xscales}; end
1290 if ~iscell(yscales), yscales = {yscales}; end
1291
1292 % collect figure handles
1293 cfig = []; cax = []; cli = [];
1294 % Legend holder
1295 legendStr = [];
1296 if ~isempty(aos)
1297
1298 % Now loop over AOs
1299 Na = length(aos);
1300
1301 % Do we want to use a unit placeholder on the yaxis?
1302 yunits = aos(1).data.yunits;
1303 yunitPlaceholder = '[Mixed]';
1304 useYunitPlaceholder = false;
1305 if strcmpi(arrangement, 'stacked')
1306 for jj = 1:Na
1307 if yunits ~= aos(jj).data.yunits
1308 useYunitPlaceholder = true;
1309 break;
1310 end
1311 end
1312 end
1313
1314 for jj = 1:Na
1315 if useYunitPlaceholder
1316 yunits = yunitPlaceholder;
1317 else
1318 yunits = aos(jj).data.yunits;
1319 end
1320
1321 % what figures do we need?
1322 switch arrangement
1323 case 'single'
1324 cfig = [cfig figure];
1325 cax = subplot(1,1,1);
1326 col = colors{1};
1327 case 'stacked'
1328 if ~isempty(fig2plot), cfig = fig2plot;
1329 elseif jj==1, cfig = figure;
1330 end
1331 % if jj==1, cfig = figure; end
1332 cax = subplot(1,1,1,'Parent',cfig);
1333 col = colors{mod(jj-1,length(colors))+1};
1334 hold on;
1335 case 'subplots'
1336 if ~isempty(fig2plot), cfig = fig2plot;
1337 elseif jj==1, cfig = figure;
1338 end
1339 % if jj == 1, cfig = figure; end
1340 cax = [cax subplot(Na, 1, jj)];
1341 col = colors{1};
1342 otherwise
1343 error('### Unknown plot arrangement');
1344 end
1345
1346 % Get data
1347 if isreal(aos(jj).data.getY)
1348 x = 1:length(aos(jj).data.getY);
1349 y = aos(jj).data.getY;
1350 else
1351 x = real(aos(jj).data.getY);
1352 y = imag(aos(jj).data.getY);
1353 end
1354
1355 %------- Apply math functions
1356 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1357 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1358 % Process errors
1359 [fcn, xu, xl, yu, yl] = process_errors(jj, size(y), type, {[]}, {[]}, YerrU, YerrL, aos(jj), autoErrors);
1360
1361 %------- Plot the data
1362 switch fcn
1363 case 'errorbar'
1364 lhs = errorbarxy(cax(end), x, y,zeros(size(yl)),yu,zeros(size(yl)),yl);
1365 idcs = lhs(1);
1366 le = lhs(2);
1367 case type
1368 idcs = feval(type, cax(end), x, y);
1369 le = false; % we have no error plots
1370 case 'errorbarxy'
1371 lhs = errorbarxy(cax(end), x, y, xu, yu, xl, yl);
1372 idcs = lhs(1);
1373 le = lhs(2);
1374 end
1375 %------- Plot the data
1376 % idcs = feval(type, cax(end), x, y);
1377 % cli = [cli idcs(1:end).'];
1378
1379 %------- Axis properties
1380
1381 % Set ylabel
1382 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1383 ylstr = prepareAxisLabel(yunits, ymath, ylstr, 'y', UseLatex);
1384 ylstr = fixlabel(ylstr);
1385 if UseLatex
1386 ylabel(ylstr, 'interpreter', 'latex');
1387 else
1388 ylabel(ylstr);
1389 end
1390
1391 % Set xlabel
1392 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1393 xlstr = prepareAxisLabel(unit('Index'), xmath, xlstr, 'x', UseLatex);
1394 xlstr = fixlabel(xlstr);
1395 if UseLatex
1396 xlabel(xlstr, 'interpreter', 'latex');
1397 else
1398 xlabel(xlstr);
1399 end
1400
1401 % Set Y scale
1402 yscale = parseOptions(jj, yscales, 'lin');
1403 set(cax(end), 'YScale', yscale);
1404
1405 % Set X scale
1406 xscale = parseOptions(jj, xscales, 'lin');
1407 set(cax(end), 'XScale', xscale);
1408
1409 % Set Y range
1410 yrange = parseOptions(jj, yranges, []);
1411 if ~isempty(yrange), set(cax(end), 'YLim', yrange); end
1412
1413 % Set X range
1414 xrange = parseOptions(jj, xranges, []);
1415 if ~isempty(xrange), set(cax(end), 'XLim', xrange); end
1416
1417 % Set grid on or off
1418 grid(cax(end), 'on');
1419
1420 %------- line properties
1421
1422 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
1423 linecolors, col, ...
1424 linestyles, '-', ...
1425 linewidths, get(0,'DefaultLineLineWidth'), ...
1426 markers, 'None');
1427
1428 % Overide line colors with user defined colors
1429 set(idcs, 'Color', col);
1430 if ~isempty(le) && ishandle(le), set(le, 'Color', col); end
1431
1432 % Set line style
1433 set(idcs, 'LineStyle', lstyle);
1434 if ishandle(le), set(le, 'LineStyle', lstyle); end
1435 % Set Markers
1436 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
1437 mkr = '.';
1438 end
1439 set(idcs, 'Marker', mkr);
1440 % Set line widths
1441 set(idcs, 'LineWidth', lwidth);
1442 if ~isempty(le) && ishandle(le), set(le, 'LineWidth', lwidth); end
1443
1444 % Set legend string
1445 if legendsOn
1446 if ~isempty(aos(jj).plotinfo) && ...
1447 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1448 ~aos(jj).plotinfo.find('LEGEND_ON')
1449 for kk=1:numel(li)
1450 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1451 end
1452 else
1453 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1454 legendStr = [legendStr cellstr(lstr)];
1455 % Set the legend now if we can
1456 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
1457 legend(fixlabel(legendStr{end}), 'Location', legendLoc);
1458 end
1459 end
1460 end
1461 end % End AO loop
1462
1463 % Process legends for stacked plots
1464 if legendsOn
1465 if strcmp(arrangement, 'stacked')
1466 if ~isempty(legendStr)
1467 h = legend(fixlabel(legendStr), 'Location', legendLoc);
1468 set(h, 'FontSize', legendsFont);
1469 end
1470 end
1471 end
1472
1473 end
1474
1475 % Apply plot settings to the figure
1476 applyPlotSettings(cax, cli);
1477
1478 % Set outputs
1479 if nargout > 0
1480 varargout{1} = cfig;
1481 end
1482 if nargout > 1
1483 varargout{2} = cax;
1484 end
1485 if nargout == 3
1486 varargout{3} = cli;
1487 end
1488 if nargout > 3
1489 error('### Too many output arguments');
1490 end
1491 end % End y_plot
1492
1493 %--------------------------------------------------------------------------
1494 % Plot xyzdata objects
1495 %
1496 function varargout = xyz_plot(varargin)
1497
1498 aos = varargin{1};
1499 pl = varargin{2};
1500 fig2plot = varargin{3};
1501
1502 UseLatex = find(pl, 'LatexLabels');
1503 if ischar(UseLatex)
1504 UseLatex = eval(UseLatex);
1505 end
1506
1507 % Extract parameters
1508 arrangement = find(pl, 'Arrangement');
1509 legends = find(pl, 'Legends');
1510 legendsFont = find(pl, 'LegendFontSize');
1511 zlabels = find(pl, 'ZLabels');
1512 ylabels = find(pl, 'YLabels');
1513 xlabels = find(pl, 'XLabels');
1514 xmaths = find(pl, 'XMaths');
1515 ymaths = find(pl, 'YMaths');
1516 zmaths = find(pl, 'ZMaths');
1517 legendLoc = find(pl, 'LegendLocation');
1518 yranges = find(pl, 'YRanges');
1519 xranges = find(pl, 'XRanges');
1520 zranges = find(pl, 'ZRanges');
1521 zscales = find(pl, 'ZScales');
1522 yscales = find(pl, 'YScales');
1523 xscales = find(pl, 'XScales');
1524 invertY = find(pl, 'InvertY');
1525
1526 % check whether we want legends or not
1527 if iscell(legends)
1528 legendsOn = 1;
1529 else
1530 if strcmp(legends, 'off')
1531 legendsOn = 0;
1532 else
1533 legendsOn = 1;
1534 legends = [];
1535 end
1536 end
1537
1538 if ~isempty(ymaths) || ~isempty(xmaths)
1539 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
1540 end
1541
1542 if ~iscell(legends), legends = {legends}; end
1543 if ~iscell(ylabels), ylabels = {ylabels}; end
1544 if ~iscell(xlabels), xlabels = {xlabels}; end
1545 if ~iscell(zlabels), zlabels = {zlabels}; end
1546 if ~iscell(xmaths), xmaths = {xmaths}; end
1547 if ~iscell(ymaths), ymaths = {ymaths}; end
1548 if ~iscell(zmaths), zmaths = {zmaths}; end
1549 if ~iscell(xranges), xranges = {xranges}; end
1550 if ~iscell(yranges), yranges = {yranges}; end
1551 if ~iscell(zranges), zranges = {zranges}; end
1552 if ~iscell(xscales), xscales = {xscales}; end
1553 if ~iscell(yscales), yscales = {yscales}; end
1554 if ~iscell(zscales), zscales = {zscales}; end
1555
1556
1557 % collect figure handles
1558 tdfig = [];
1559 tdax = [];
1560 tdli = [];
1561
1562 % Legend holder
1563 legendStr = [];
1564
1565 if ~isempty(aos)
1566
1567 % Now loop over AOs
1568 Na = length(aos);
1569 for jj = 1:Na
1570 % what figures do we need?
1571 switch arrangement
1572 case 'single'
1573 tdfig = [tdfig figure];
1574 tdax = subplot(1,1,1);
1575 case 'subplots'
1576 if ~isempty(fig2plot), tdfig = fig2plot;
1577 elseif jj==1, tdfig = figure;
1578 end
1579 % if jj == 1, tdfig = figure; end
1580 tdax = [tdax subplot(Na, 1, jj)];
1581 otherwise
1582 warning('!!! Plot arrangement ''%s'' not supported on XYZ plots. Using ''single'' instead.', arrangement);
1583 arrangment = 'single';
1584 tdfig = [tdfig figure];
1585 tdax = subplot(1,1,1);
1586 end
1587
1588 %------- Apply math functions
1589 x = aos(jj).data.x;
1590 y = aos(jj).data.getY;
1591 z = aos(jj).data.z;
1592
1593 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1594 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1595 zmath = parseOptions(jj, zmaths, 'z'); eval(sprintf('z = %s;', zmath));
1596
1597 %------- Plot the data
1598
1599 idcs = pcolor(x,y,z);
1600 tdli = [tdli idcs(1:end).'];
1601
1602 % plot properties
1603 set(idcs, 'EdgeColor', 'none');
1604
1605 %------- Axis properties
1606
1607 % Reverse y-direction for spectrograms
1608 if invertY
1609 set(tdax(end), 'YDir', 'reverse');
1610 end
1611
1612 % Set ylabel
1613 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1614 ylstr = prepareAxisLabel(aos(jj).data.yunits, ymath, ylstr, 'y', UseLatex);
1615 ylstr = fixlabel(ylstr);
1616 if UseLatex
1617 ylabel(ylstr, 'interpreter', 'latex');
1618 else
1619 ylabel(ylstr);
1620 end
1621
1622 % Set xlabel
1623 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1624 xlstr = prepareAxisLabel(aos(jj).data.xunits, xmath, xlstr, 'x', UseLatex);
1625 xlstr = fixlabel(xlstr);
1626 if UseLatex
1627 xlabel(xlstr, 'interpreter', 'latex');
1628 else
1629 xlabel(xlstr);
1630 end
1631
1632 % Set grid on or off
1633 grid(tdax(end), 'on');
1634
1635 % Set title string
1636 if legendsOn
1637 if ~isempty(aos(jj).plotinfo) && ...
1638 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1639 ~aos(jj).plotinfo.find('LEGEND_ON')
1640 for kk=1:numel(li)
1641 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1642 end
1643 else
1644 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1645 legendStr = [legendStr cellstr(lstr)];
1646 % Set the legend now if we can
1647 title(legendStr{end});
1648 end
1649 end
1650
1651 % Set colorbars
1652 hc = colorbar('peer', tdax(end));
1653 zlstr = parseOptions(jj, zlabels, find(pl, 'Zlabels'));
1654 zlstr = prepareAxisLabel(aos(jj).data.zunits, zmath, zlstr, 'z', UseLatex);
1655 zlstr = fixlabel(zlstr);
1656 ylh = get(hc, 'YLabel');
1657 set(ylh, 'String', zlstr);
1658 set(ylh, 'Fontsize', get(tdax(end), 'Fontsize'))
1659 set(ylh, 'FontName', get(tdax(end), 'FontName'))
1660 set(ylh, 'FontAngle', get(tdax(end), 'FontAngle'))
1661 set(ylh, 'FontWeight', get(tdax(end), 'FontWeight'))
1662
1663
1664 % Set Y scale
1665 yscale = parseOptions(jj, yscales, 'lin');
1666 set(tdax(end), 'YScale', yscale);
1667
1668 % Set X scale
1669 xscale = parseOptions(jj, xscales, 'lin');
1670 set(tdax(end), 'XScale', xscale);
1671
1672 % Set Z scale
1673 zscale = parseOptions(jj, zscales, 'lin');
1674 set(tdax(end), 'ZScale', zscale);
1675
1676 % Set Y range
1677 yrange = parseOptions(jj, yranges, []);
1678 if ~isempty(yrange), set(tdax(end), 'YLim', yrange); end
1679
1680 % Set X range
1681 xrange = parseOptions(jj, xranges, []);
1682 if ~isempty(xrange), set(tdax(end), 'XLim', xrange); end
1683
1684 % Set Z range
1685 zrange = parseOptions(jj, zranges, []);
1686 if ~isempty(zrange), set(tdax(end), 'CLim', zrange); end
1687 end
1688 end
1689
1690 % Apply plot settings to the figure
1691 applyPlotSettings(tdax, tdli);
1692
1693 % Set outputs
1694 if nargout > 0
1695 varargout{1} = tdfig;
1696 end
1697 if nargout > 1
1698 varargout{2} = tdax;
1699 end
1700 if nargout == 3
1701 varargout{3} = tdli;
1702 end
1703 if nargout > 3
1704 error('### Too many output arguments');
1705 end
1706 end % end xyz_plot
1707
1708 %--------------------------------------------------------------------------
1709 % Get Info Object
1710 %--------------------------------------------------------------------------
1711 function ii = getInfo(varargin)
1712 if nargin == 1 && strcmpi(varargin{1}, 'None')
1713 sets = {};
1714 pl = [];
1715 elseif nargin == 1&& ~isempty(varargin{1}) && ischar(varargin{1})
1716 sets{1} = varargin{1};
1717 pl = getDefaultPlist(sets{1});
1718 else
1719 sets = {'Time-series Plot', 'Frequency-series Plot', 'Y Data Plot', 'X-Y Data Plot', '3D Plot'};
1720 % get plists
1721 pl(size(sets)) = plist;
1722 for k = 1:numel(sets)
1723 pl(k) = getDefaultPlist(sets{k});
1724 end
1725 end
1726 % Build info object
1727 ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.output, '$Id: iplot.m,v 1.139 2011/06/01 13:08:47 hewitson Exp $', sets, pl);
1728 ii.setModifier(false);
1729 ii.setOutmin(0);
1730 end
1731
1732 % Parse line properties from plist, or defaults
1733 function [col, lstyle, lwidth, mkr] = parseLineProps(jj, pli, ...
1734 linecolors, dcol, ...
1735 linestyles, dlstyle, ...
1736 linewidths, dlwidth, ...
1737 markers, dmkr)
1738
1739 if isempty(pli)
1740 pli = plist;
1741 end
1742
1743 % Set line color but overide with user colors
1744 col = pli.find('color');
1745 if isempty(col)
1746 col = parseOptions(jj, linecolors, dcol);
1747 end
1748
1749 % Set line style
1750 lstyle = pli.find('linestyle');
1751 if isempty(lstyle)
1752 lstyle = parseOptions(jj, linestyles, dlstyle);
1753 end
1754
1755 % Set line widths
1756 lwidth = pli.find('linewidth');
1757 if isempty(lwidth)
1758 lwidth = parseOptions(jj, linewidths, dlwidth);
1759 end
1760
1761 % Set markers
1762 mkr = pli.find('marker');
1763 if isempty(mkr)
1764 mkr = parseOptions(jj, markers, dmkr);
1765 end
1766
1767 end
1768
1769
1770 %--------------------------------------------------------------------------
1771 % Get Default Plist
1772 %--------------------------------------------------------------------------
1773 function plout = getDefaultPlist(set)
1774 persistent pl;
1775 persistent lastset;
1776 if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
1777 pl = buildplist(set);
1778 lastset = set;
1779 end
1780 pl.pset('LEGENDFONTSIZE', LTPDAprefs.legendFontSize);
1781 plout = pl;
1782 end
1783
1784 function out = buildplist(set)
1785
1786 % Get the LTPDA color set for lines
1787 colors = getappdata(0,'ltpda_default_plot_colors');
1788
1789 out = plist();
1790
1791 % Figure
1792 p = param({'Figure',['The handle of the figure to plot in to. This will be ignored if the AOs to plot are inconsistent,<br>'...
1793 'containing different class of data (such as tsdata and fsdata), or if the ''arrangement''<br>',...
1794 'parameter is passed as ''single''.']}, paramValue.EMPTY_DOUBLE);
1795 out.append(p);
1796
1797 % Colors
1798 p = param({'Colors', 'A list of colors which will be cycled through for each line in a plot.'}, colors);
1799 out.append(p);
1800
1801 % Arrangement
1802 p = param({'Arrangement',['Select the plot layout:<ul>',...
1803 '<li>''single'' - plot all AOs on individual figures</li>',...
1804 '<li>''stacked'' - plot all AOs on the same axes</li>',...
1805 '<li>''subplots'' - plot all AOs on subplots</li>'...
1806 '</ul>']}, {1, {'stacked', 'single', 'subplots'}, paramValue.SINGLE});
1807 out.append(p);
1808
1809 % Function
1810 p = param({'Function',['Specify the plot function:<ul>',...
1811 '<li>''plot''</li>', ...
1812 '<li>''stairs''</li>',...
1813 '<li>''stem''</li>',...
1814 '</ul>'...
1815 '[*** doesn''t work for xyzdata AOs]']}, {1, {'plot', 'stairs', 'stem'}, paramValue.SINGLE});
1816 out.append(p);
1817
1818 % LineColors
1819 p = param({'LineColors', ['A cell-array of color definitions, one for each trace.<br>'...
1820 'Give an empty string to use the default color.']}, ...
1821 {1, {''}, paramValue.OPTIONAL});
1822 out.append(p);
1823
1824 % LineColors
1825 p = param({'LineStyles', ['A cell-array of line styles, one for each trace.<br>'...
1826 'Give an empty string to use the default style.']}, ...
1827 {1, {''}, paramValue.OPTIONAL});
1828 out.append(p);
1829
1830 % Markers
1831 p = param({'Markers', ['A cell-array of markers, one for each trace.']}, ...
1832 {1, {''}, paramValue.OPTIONAL});
1833 out.append(p);
1834
1835 % LineWidths
1836 p = param({'LineWidths', ['A cell-array of line widths, one for each trace.<br>'...
1837 'Give an empty string to use the default line width.']}, ...
1838 {1, {''}, paramValue.OPTIONAL});
1839 out.append(p);
1840
1841 % Legends
1842 p = param({'Legends', ['Give a cell-array of strings to be used for<br>'...
1843 'the plot legends. If a cell contains an empty<br>'...
1844 'string, the default legend string is built.<br>'...
1845 'If a single string ''off'' is given instead of a<br>'...
1846 'cell-array, then the legends are all switched off.']}, ...
1847 {1, {''}, paramValue.OPTIONAL});
1848 out.append(p);
1849
1850 % LegendLocation
1851 p = param({'LegendLocation','Choose the legend location.'}, ...
1852 {5, {'North', 'South', 'East', 'West', ...
1853 'NorthEast', 'NorthWest', 'SouthEast', 'SouthWest', ...
1854 'NorthOutside', 'SouthOutside', 'EastOutside', 'WestOutside', ...
1855 'NorthEastOutside', 'NorthWestOutside', 'SouthEastOutside', ...
1856 'SouthWestOutside', 'Best', 'BestOutside'}, paramValue.SINGLE});
1857 out.append(p);
1858
1859 % LegendFontSize
1860 p = param({'LegendFontSize','Choose the legend font size.'}, ...
1861 {1, {LTPDAprefs.legendFontSize}, paramValue.SINGLE});
1862 out.append(p);
1863
1864 % XerrL
1865 p = param({'XerrL','Lower bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1866 out.append(p);
1867
1868 % XerrU
1869 p = param({'XerrU','Upper bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1870 out.append(p);
1871
1872 % YerrL
1873 p = param({'YerrL','Lower bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1874 out.append(p);
1875
1876 % YerrU
1877 p = param({'YerrU','Upper bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1878 out.append(p);
1879
1880 % XScales
1881 p = param({'XScales', ['A cell-array specifying the scale to be used on each x-axis.<br>'...
1882 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1883 out.append(p);
1884
1885 % YScales
1886 p = param({'YScales', ['A cell-array specifying the scale to be used on each y-axis.<br>'...
1887 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1888 out.append(p);
1889
1890 % XRanges
1891 p = param({'XRanges', ['A cell-array specifying the ranges to be displayed on each x-axis.<br>'...
1892 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1893 out.append(p);
1894
1895 % YRanges
1896 p = param({'YRanges', ['A cell-array specifying the ranges to be displayed on each y-axis.<br>'...
1897 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1898 out.append(p);
1899
1900 % LatexLabels
1901 p = param({'LatexLabels','Use latex interpreter for axis labels.'}, paramValue.TRUE_FALSE);
1902 p.val.setValIndex(2);
1903 out.append(p);
1904
1905 % YMaths
1906 p = param({'YMaths',['Specify math operations to perform on the data vector ''y''. [DEPRECATED]<br>',...
1907 'For example, <tt>plist(''Ymaths'', ''sqrt(y)'')</tt>.']}, paramValue.EMPTY_STRING);
1908 out.append(p);
1909
1910
1911 % No auto-errors
1912 p = param({'AUTOERRORS',['If the AO contains errors, they will be plotted. You can avoid plotting the <br>',...
1913 'errors by setting this to false.']}, paramValue.FALSE_TRUE);
1914 out.append(p);
1915
1916 switch lower(set)
1917 case 'frequency-series plot'
1918 % ComplexPlotType
1919 p = param({'complexPlotType',['Specify how to plot complex data. Choose from:<ul>',...
1920 '<li>''realimag''</li>',...
1921 '<li>''absdeg''</li>',...
1922 '<li>''absrad''</li>'...
1923 '</ul>']}, {1, {'absdeg', 'realimag', 'absrad'}, paramValue.SINGLE});
1924 out.append(p);
1925
1926 % Xlabel
1927 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1928 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1929 out.append(p);
1930 % ylabels
1931 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1932 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE(''));
1933 out.append(p);
1934
1935 % XMaths
1936 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1937 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1938 out.append(p);
1939
1940 case 'time-series plot'
1941
1942 % Xlabel
1943 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1944 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1945 out.append(p);
1946
1947 % Ylabels
1948 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1949 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
1950 out.append(p);
1951
1952 % Xunits
1953 p = param({'Xunits', ['Specify the units of time on the x-axis as<ul>'...
1954 '<li>''us'' - microseconds<li>' ...
1955 '<li>''ms'' - milliseconds<li>' ...
1956 '<li>''s'' - seconds<li>' ...
1957 '<li>''m'' - minutes<li>' ...
1958 '<li>''h'' - hours<li>' ...
1959 '<li>''D'' - days<li>' ...
1960 '<li>''M'' - months<li>' ...
1961 '<li>''HH:MM:SS'' - using a date/time format</li>' ...
1962 '</ul>']}, {3, {'us', 'ms', 's', 'm', 'h', 'D', 'M', 'HH:MM:SS', 'yyyy-mm-dd HH:MM:SS'}, paramValue.OPTIONAL});
1963 out.append(p);
1964
1965 case 'x-y data plot'
1966 % Xlabel
1967 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1968 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('X-data'));
1969 out.append(p);
1970
1971 % Ylabels
1972 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1973 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Y-data'));
1974 out.append(p);
1975
1976 % XMaths
1977 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1978 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1979 out.append(p);
1980
1981 case '3d plot'
1982
1983 out.pset('arrangement', 'single');
1984
1985 % Xlabel
1986 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1987 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1988 out.append(p);
1989
1990 % Ylabels
1991 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1992 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1993 out.append(p);
1994
1995 % Zlabels
1996 p = param({'ZLabels',['Specify the labels to be used on the z-axes. The units are added from<br>',...
1997 'the data object ''zunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
1998 out.append(p);
1999
2000 % XMaths
2001 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
2002 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
2003 out.append(p);
2004
2005 % ZMaths
2006 p = param({'ZMaths',['Specify math operations to perform on the data vector ''z''. [DEPRECATED]<br>',...
2007 'For example, <tt>plist(''Zmaths'', ''abs(z)'')</tt>.']}, paramValue.EMPTY_STRING);
2008 out.append(p);
2009
2010 % ZScales
2011 p = param({'ZScales', ['A cell-array specifying the scale to be used on each z-axis.<br>'...
2012 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
2013 out.append(p);
2014
2015 % ZRanges
2016 p = param({'ZRanges', ['A cell-array specifying the ranges to be displayed on each z-axis.<br>'...
2017 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
2018 out.append(p);
2019
2020 % Invert y-axis
2021 p = param({'InvertY', ['Invert the y-axis or not.']}, paramValue.TRUE_FALSE);
2022 out.append(p);
2023
2024 out.remove('linestyles');
2025 out.remove('linewidths');
2026 out.remove('linecolors');
2027 out.remove('markers');
2028
2029 case 'y data plot'
2030 % Xlabel
2031 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
2032 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Sample'));
2033 out.append(p);
2034
2035 % Ylabels
2036 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
2037 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Value'));
2038 out.append(p);
2039 otherwise
2040 error('### Unknown set [%s]', set);
2041 end
2042 end
2043
2044
2045 function name = makeLegendStr(a)
2046
2047 name = utils.plottools.label(a.name);
2048 desc = utils.plottools.label(a.description);
2049
2050 if isempty(name)
2051 name = '?';
2052 end
2053
2054 if ~isempty(desc) && LTPDAprefs.includeDescription
2055 name = [name ': ' desc];
2056 end
2057
2058
2059 end
2060
2061 % Perform some substitutions on the labels
2062 function ss = fixlabel(ss)
2063
2064 MAX_LENGTH = 100;
2065 wasCell = true;
2066 if ~iscell(ss)
2067 ss = {ss};
2068 wasCell = false;
2069 end
2070
2071 for kk = 1:numel(ss)
2072 s = ss{kk};
2073 if ~isempty(s)
2074 % Replace all ^(...) with ^{...}
2075 jj = 1;
2076 while jj < numel(s)
2077 if strcmp(s(jj:jj+1), '^(')
2078 % find next )
2079 for k = 1:numel(s)-jj+1
2080 if s(jj+k) == ')'
2081 s(jj+1) = '{';
2082 s(jj+k) = '}';
2083 break;
2084 end
2085 end
2086 end
2087 jj = jj + 1;
2088 end
2089 % Replace all .^ with ^
2090 s = strrep(s, '.^', '^');
2091
2092 % reduce size
2093 if length(s) > MAX_LENGTH
2094 s = s(1:MAX_LENGTH-3);
2095 if s(end) == '\'
2096 s = s(1:end-1)
2097 end
2098 s = [ s '...' ];
2099 end
2100
2101 end
2102 ss(kk) = {s};
2103 end
2104
2105 if ~wasCell
2106 ss = ss{1};
2107 end
2108
2109 end
2110
2111 %-----------------------------------------------
2112 % Change X data for time-series according to the specified xunits
2113 function [x, xunit, dateTicSpec] = convertXunits(x, t0, xunit, xunitIn)
2114
2115 dateTicSpec = false;
2116
2117 xunit = strtrim(xunit);
2118 xunitIn = strtrim(xunitIn);
2119 if ~strcmpi(strtrim(xunitIn), '[s]')
2120 warning('### I can only convert from [s] to %s - ignoring requested Xunit', xunit);
2121 xunit = xunitIn;
2122 else
2123 switch strtrim(xunit)
2124 case {'[us]', 'us'}
2125 x = x .* 1e6;
2126 case {'[ms]', 'ms'}
2127 x = x .* 1e3;
2128 case {'[s]', 's'}
2129 case {'[m]', 'm'}
2130 x = x ./ 60;
2131 case {'[h]', 'h'}
2132 x = x ./ 3600;
2133 case {'[D]', 'D'}
2134 x = x ./ 86400;
2135 otherwise
2136 % then we have a datetic spec
2137 dateTicSpec = true;
2138 % first convert x data to serial date
2139 st = format(t0, 'yyyy-mm-dd hh:mm:ss');
2140 st = regexp(st, ' ', 'split');
2141 st = [st{1} ' ' st{2}];
2142 t0 = datenum(st); % get t0 as a serial date
2143 x = t0 + x./86400; % convert x to days
2144 end
2145 end
2146 if xunit(1) ~= '['
2147 xunit = ['[' xunit];
2148 end
2149 if xunit(end) ~= ']'
2150 xunit = [xunit ']'];
2151 end
2152 % 'us' - microseconds
2153 % 'ms' - milliseconds
2154 % 's' - seconds [default]
2155 % 'm' - minutes
2156 % 'h' - hours
2157 % 'D' - days
2158 % 'M' - months
2159 % 'HH:MM:SS' - using a date/time format
2160
2161 end
2162
2163 %----------------------------------------
2164 % Prepare an axis label
2165 function lstr = prepareAxisLabel(units, math, lstr, axis, UseLatex)
2166 if isa(units, 'unit')
2167
2168 if ismac && UseLatex
2169 units = units.tolabel;
2170 else
2171 units = {fixlabel(char(units))};
2172 end
2173 else
2174 units = {units};
2175 end
2176 if ~isempty(math)
2177 if ~isempty(lstr)
2178 lstr = strrep(math, axis, lstr);
2179 end
2180 lstr = [fixlabel(lstr) ' ' units{1} ];
2181 else
2182 lstr = [fixlabel(lstr) ' ' units{1}];
2183 end
2184 end
2185
2186 % Parse cell-array of options
2187 function opt = parseOptions(varargin) %jj, opts, dopt
2188
2189 jj = varargin{1};
2190 opts = varargin{2};
2191 dopt = varargin{3};
2192 opt = dopt;
2193
2194 if ~iscell(opts)
2195 opts = {opts};
2196 end
2197 Nopts = numel(opts);
2198
2199 % First look for the 'all' keyword
2200 if Nopts == 2 && strcmpi(opts{1}, 'all')
2201 opt = opts{2};
2202 else
2203 if jj <= Nopts && ~isempty(opts{jj})
2204 opt = opts{jj};
2205 end
2206 end
2207
2208 end
2209
2210
2211
2212 % ERRORBARXY Customizable error bar plot in X and Y direction
2213 %
2214 % This function allows the user to plot the graph of x against y, along with
2215 % both x and y errorbars.
2216 %
2217 % With 4 numeric arguments (x,y,dx,dy), error bar are assumed to be of
2218 % same magnitude in both direction.
2219 %
2220 % One can specify lower and upper error bar with 6 numeric arguments
2221 % (x,y,dx_high,dy_high,dx_low,dy_low).
2222 %
2223 % x,y,dx,dy,... must be vectors of the same length
2224 %
2225 % [hp he] = errorbarxy(...) returns respectively the handle for the line
2226 % plot object and the line error bar object.
2227 %
2228 % It is possible to customize the line properties of the error bars by
2229 % adding pair of 'field/value' fields (such as 'LineWidth',2) that can be
2230 % understood by line. See LineProperties for more information.
2231 %
2232 % --------
2233 % EXAMPLES
2234 % --------
2235 % X = 10 * rand(7,1);
2236 % Y = 10 * rand(7,1);
2237 % dx = rand(7,1);
2238 % dy = rand(7,1);
2239 % errorbarxy(X,Y,dx,dy,'Color','k','LineStyle','none','Marker','o',...
2240 % 'MarkerFaceColor','w','LineWidth',1,'MarkerSize',11);
2241 %
2242 % X = 10 * rand(7,1);
2243 % Y = 10 * rand(7,1);
2244 % dx = rand(7,1);
2245 % dy = rand(7,1);
2246 % dx2 = rand(7,1);
2247 % dy2 = rand(7,1);
2248 % errorbarxy(X,Y,dx,dy,dx2,dy2,'Color','B','LineStyle','--','Marker','s',...
2249 % 'MarkerFaceColor','w','LineWidth',2,'MarkerSize',11);
2250 %
2251 % This is a rewrite of the m-file errorbarxy of James Rooney, to add
2252 % customizable line properties.
2253
2254 % ------------------ INFO ------------------
2255 % Authors: Jean-Yves Tinevez
2256 % Work address: Max-Plank Insitute for Cell Biology and Genetics,
2257 % Dresden, Germany.
2258 % Email: tinevez AT mpi-cbg DOT de
2259 % November 2007 - June 2008;
2260 % Permission is given to distribute and modify this file as long as this
2261 % notice remains in it. Permission is also given to write to the author
2262 % for any suggestion, comment, modification or usage.
2263 % ------------------ BEGIN CODE ------------------
2264
2265 function out = errorbarxy(ax, x,y,varargin)
2266
2267
2268 nargs = length(varargin);
2269
2270 for i = 1 : nargs
2271
2272 if ~( isnumeric(varargin{i}) )
2273 break
2274 end
2275 errbaropt{i} = varargin{i};
2276
2277 end
2278
2279
2280 if i+3 < nargin
2281 displayopt = varargin(i:end);
2282 if isstruct(displayopt{1})
2283 options = displayopt{1};
2284 else
2285 options = varargin2struct(displayopt);
2286 end
2287 erroroptions = options;
2288 else
2289 displayopt = [];
2290 end
2291
2292 options.Color = 'k';
2293 erroroptions.LineStyle = '-';
2294 erroroptions.Marker = 'none';
2295
2296
2297 xw = (max(x)-min(x))/100;
2298 yw = (max(y)-min(y))/100;
2299
2300 n = length(varargin) - length(displayopt);
2301
2302 if n == 2
2303 % only 2 cells, so this is the same for lower and upper bar
2304 ux = errbaropt{1};
2305 lx = ux;
2306 uy = errbaropt{2};
2307 ly = uy;
2308
2309 elseif n == 4
2310 % 4 cells, the user specified both upper and lower limit
2311 ux = errbaropt{1};
2312 lx = errbaropt{3};
2313 uy = errbaropt{2};
2314 ly = errbaropt{4};
2315
2316 else
2317 errid = 'MATLAB:errorbarxy:BadArgumentNumber';
2318 errmsg = ['Must have 4 or 6 numeric arguments, got ' ,num2str(n+2),'.'];
2319 error(errid,errmsg);
2320
2321 end
2322
2323
2324 %%
2325
2326 holdstate = ishold(gca);
2327 X = [];
2328 Y = [];
2329 for t = 1:length(x)
2330
2331 % x errorbars
2332 X = [ X nan x(t)-lx(t) x(t)+ux(t) nan x(t)-lx(t) x(t)-lx(t) nan x(t)+ux(t) x(t)+ux(t) ];
2333 Y = [ Y nan y(t) y(t) nan y(t)-yw y(t)+yw nan y(t)-yw y(t)+yw ];
2334
2335 % y errorbars
2336 X = [ X nan x(t) x(t) nan x(t)-xw x(t)+xw nan x(t)-xw x(t)+xw ];
2337 Y = [ Y nan y(t)-ly(t) y(t)+uy(t) nan y(t)-ly(t) y(t)-ly(t) nan y(t)+uy(t) y(t)+uy(t) ];
2338
2339 end
2340
2341 hold on
2342 axes(ax);
2343 he = line(X,Y,erroroptions);
2344 hp = plot(ax, x,y,options);
2345 out = [hp he];
2346
2347 % Return to initial hold state if needed
2348 if ~holdstate
2349 hold off
2350 end
2351
2352 function out = varargin2struct(in)
2353 % I hould write help
2354
2355 if ~iscell(in)
2356 errid = 'MATLAB:struct2varargin:BadInputType';
2357 errmsg = ['Input argument must be a cell, got a ' ,class(in),'.'];
2358 error(errid,errmsg);
2359 end
2360
2361 n = length(in);
2362
2363 if mod(n,2) ~= 0
2364 errid = 'MATLAB:struct2varargin:BadInputType';
2365 errmsg = ['Input argument must have an even number of elements, got ' ,num2str(n),'.'];
2366 error(errid,errmsg);
2367 end
2368
2369 out = struct;
2370
2371 for jj = 1 : n/2
2372 name = in{2*jj-1};
2373 value = in{2*jj};
2374 out.(name) = value;
2375 end
2376
2377 end
2378
2379 end
2380
2381 % Get a suitable ymin and ymax (in logscale) for the given
2382 % data.
2383 function [ticks,ymin,ymax] = getRealYDataTicks(y, ymin, ymax, complexPlotType, scale)
2384
2385 ticks = [];
2386 switch complexPlotType
2387 case 'realimag'
2388 if strcmpi(scale', 'log')
2389
2390 % do nothing because it doesn't make sense since we will have
2391 % negative values on a log scale
2392
2393 end
2394 case {'absdeg', 'absrad'}
2395
2396 if strcmpi(scale, 'log')
2397 % This is the main case we want to cover.
2398 ay = abs(y);
2399 newymin = min(ymin, floor(log10(min(ay(ay>0)))));
2400 newymax = max(ymax, ceil(log10(max(ay(ay>0)))));
2401
2402 if ~isempty(newymin) && ~isempty(newymax)
2403 ymin = newymin;
2404 ymax = newymax;
2405
2406 if ymin == ymax
2407 ymin = floor(log10(min(ay)/10));
2408 ymax = ceil(log10(max(ay)*10));
2409 end
2410
2411 else
2412
2413 if ymin == inf
2414 ymin = -1;
2415 end
2416
2417 if ymax == -inf
2418 ymax = 1;
2419 end
2420
2421 end
2422 nticks = ymax - ymin +1;
2423 % can we reduce this if they don't all fit?
2424
2425 ticks = logspace(ymin, ymax, nticks);
2426 end
2427
2428 otherwise
2429 error('### Unknown plot type for complex data');
2430 end
2431
2432 end
2433
2434 % Get a suitable ymin and ymax (in linscale) for the given
2435 % data.
2436 function ticks = getImagYDataTicks(y, ymin, ymax, complexPlotType, scale)
2437
2438
2439 ticks = [];
2440 switch complexPlotType
2441 case 'realimag'
2442 if strcmpi(scale', 'log')
2443
2444 % do nothing because it doesn't make sense since we will have
2445 % negative values on a log scale
2446
2447 end
2448 case 'absdeg'
2449
2450 if strcmpi(scale', 'log')
2451 % do nothing because it doesn't make sense since we will have
2452 % negative values on a log scale
2453 end
2454
2455 case 'absrad'
2456
2457 otherwise
2458 error('### Unknown plot type for complex data');
2459 end
2460
2461
2462 end
2463
2464
2465 %-------------------
2466 % Process errorbars
2467 function [fcn, xu, xl, yu, yl] = process_errors(jj, dsize, ptype, XerrU, XerrL, YerrU, YerrL, a, auto)
2468
2469 if numel(XerrL) == 1
2470 xl = XerrL{1};
2471 else
2472 xl = XerrL{jj};
2473 end
2474 if numel(XerrU) == 1
2475 xu = XerrU{1};
2476 else
2477 xu = XerrU{jj};
2478 end
2479 if numel(YerrL) == 1
2480 yl = YerrL{1};
2481 else
2482 yl = YerrL{jj};
2483 end
2484 if numel(YerrU) == 1
2485 yu = YerrU{1};
2486 else
2487 yu = YerrU{jj};
2488 end
2489
2490 % Check if we have AOs
2491 if isa(xl, 'ao'), xl = xl.data.getY; end
2492 if isa(xu, 'ao'), xu = xu.data.getY; end
2493 if isa(yl, 'ao'), yl = yl.data.getY; end
2494 if isa(yu, 'ao'), yu = yu.data.getY; end
2495
2496 if isempty(xl) && ~isempty(xu)
2497 xl = xu;
2498 end
2499 if isempty(xu) && ~isempty(xl)
2500 xu = xl;
2501 end
2502 if isempty(yl) && ~isempty(yu)
2503 yl = yu;
2504 end
2505 if isempty(yu) && ~isempty(yl)
2506 yu = yl;
2507 end
2508
2509
2510
2511 % If the AO has errors, we use them
2512 if ~isempty(a.dy) && auto
2513 yl = a.dy;
2514 yu = a.dy;
2515 yu(yu==inf) = 0;
2516 yl(yl==inf) = 0;
2517 end
2518
2519 if isempty(xl) && isempty(xu) && isempty(yu) && isempty(yl)
2520 fcn = ptype;
2521 elseif isempty(xl) && isempty(xu)
2522 fcn = 'errorbar';
2523 else
2524 fcn = 'errorbarxy';
2525 end
2526
2527 if isempty(xl), xl = zeros(dsize); end
2528 if isempty(yl), yl = zeros(dsize); end
2529 if isempty(xu), xu = zeros(dsize); end
2530 if isempty(yu), yu = zeros(dsize); end
2531 if numel(xl) == 1, xl = xl.*ones(dsize); end
2532 if numel(xu) == 1, xu = xu.*ones(dsize); end
2533 if numel(yu) == 1, yu = yu.*ones(dsize); end
2534 if numel(yl) == 1, yl = yl.*ones(dsize); end
2535 end
2536
2537 function applyPlotSettings(axesH, lineH)
2538
2539 prefs = getappdata(0, 'LTPDApreferences');
2540 jPlotPrefs = prefs.getPlotPrefs();
2541
2542 if jPlotPrefs.getPlotApplyPlotSettings.equals(mpipeline.ltpdapreferences.EnumPlotSetting.IPLOT_ONLY)
2543
2544 % Set all axes properteis
2545 for ii =1:numel(axesH)
2546 set(axesH(ii), 'FontSize', double(jPlotPrefs.getPlotDefaultAxesFontSize));
2547 set(axesH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultAxesLineWidth));
2548 set(axesH(ii), 'GridLineStyle', char(jPlotPrefs.getPlotDefaultAxesGridLineStyle));
2549 set(axesH(ii), 'MinorGridLineStyle', char(jPlotPrefs.getPlotDefaultAxesMinorGridLineStyle));
2550 switch char(jPlotPrefs.getPlotDefaultAxesFontWeight)
2551 case 'Plain'
2552 set(axesH(ii), 'FontWeight', 'normal');
2553 case 'Bold'
2554 set(axesH(ii), 'FontWeight', 'bold');
2555 case 'Italic'
2556 set(axesH(ii), 'FontWeight', 'light');
2557 case 'Bold Italic'
2558 set(axesH(ii), 'FontWeight', 'demi');
2559 otherwise
2560 error('### Unknown value (%s) for the default axes property ''FontWeight''', char(jPlotPrefs.getPlotDefaultAxesFontWeight));
2561 end
2562 end
2563
2564 % Set all line properties
2565 for ii = 1:numel(lineH)
2566 set(lineH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultLineLineWidth));
2567 set(lineH(ii), 'MarkerSize', double(jPlotPrefs.getPlotDefaultLineMarkerSize));
2568 end
2569 end
2570 end