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