comparison m-toolbox/classes/@ao/iplot.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1 % 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.142 2011/08/15 06:08:28 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 else
712 % go back to matlab autoscale
713 set(fsax_r, 'ylimmode', 'auto');
714 set(fsax_r, 'Ytick', []);
715 set(fsax_r, 'Ytickmode', 'auto');
716
717 end
718 end
719 yrange = parseOptions(c+1, yranges, []);
720 if ~isempty(fsax_i) && ishandle(fsax_i)
721 if ~isempty(yrange)
722 set(fsax_i, 'YLim', yrange);
723 elseif strcmpi(yscaleI, 'log')
724
725 % This doesn't really make sense since the imaginary part or
726 % phase or angle will always contain negative parts. Would the
727 % user really choose a log scale in that case?
728 % tcks = getImagYDataTicks(y, ymin, ymax, complexPlotType, yscaleI);
729 % if ~isempty(tcks)
730 % yrange = [tcks(1) tcks(end)];
731 % set(fsax_i, 'YLim', yrange);
732 % set(fsax_i, 'Ytickmode', 'manual');
733 % set(fsax_i, 'Ytick', tcks);
734 % end
735 end
736 end
737
738 % Set X range
739 xrange = parseOptions(c, xranges, []);
740 if ~isempty(xrange)
741 set(fsax_r, 'XLim', xrange);
742 elseif strcmpi(xscaleR, 'log')
743 xmin = min(xmin, floor(log10(min(x(x>0)))));
744 xmax = max(xmax, ceil(log10(max(x(x>0)))));
745 tcks = logspace(xmin, xmax, xmax - xmin +1);
746 xrange = [tcks(1) tcks(end)];
747 set(fsax_r, 'XLim', xrange);
748 set(fsax_r, 'Xtickmode', 'manual');
749 set(fsax_r, 'Xtick', tcks);
750 end
751 xrange = parseOptions(c+1, xranges, []);
752 if ~isempty(fsax_i) && ishandle(fsax_i)
753 if ~isempty(xrange)
754 set(fsax_i, 'XLim', xrange);
755 elseif strcmpi(xscaleR, 'log')
756 xmin = min(xmin, floor(log10(min(x(x>0)))));
757 xmax = max(xmax, ceil(log10(max(x(x>0)))));
758 tcks = logspace(xmin, xmax, xmax - xmin +1);
759 xrange = [tcks(1) tcks(end)];
760 set(fsax_i, 'XLim', xrange);
761 set(fsax_i, 'Xtickmode', 'manual');
762 set(fsax_i, 'Xtick', tcks);
763 end
764 end
765
766 %------- line properties
767 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
768 linecolors, col, ...
769 linestyles, '-', ...
770 linewidths, get(0,'DefaultLineLineWidth'), ...
771 markers, 'None');
772
773 % set props
774 set(li, 'Color', col);
775 set(li, 'LineStyle', lstyle);
776 set(li, 'LineWidth', lwidth);
777 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
778 mkr = '.';
779 end
780 set(li, 'Marker', mkr);
781
782 % Set legend string
783 if legendsOn
784 if ~isempty(aos(jj).plotinfo) && ...
785 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
786 ~aos(jj).plotinfo.find('LEGEND_ON')
787 for kk=1:numel(li)
788 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
789 end
790 else
791 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
792 legendStrR = [legendStrR cellstr(lstr)];
793 if ~isreal(y)
794 legendStrI = [legendStrI cellstr(lstr)];
795 end
796 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
797 legend(fsax_r, fixlabel(legendStrR{end}), 'Location', legendLoc);
798 if ~isempty(fsax_i) && ishandle(fsax_i)
799 h = legend(fsax_i, fixlabel(legendStrI), 'Location', legendLoc);
800 end
801 end
802 end
803 end
804
805 end % End loop over AOs
806
807 % Make sure the plots are refreshed
808 drawnow();
809 % Trim the size of complex plots
810 for jj = 1:length(complexFig)
811 p_r = get(complexAxes(2*jj-1), 'Position');
812 p_i = get(complexAxes(2*jj), 'Position');
813 dh = (p_r(2) - (p_i(2)+p_i(4)))/3;
814 set(complexAxes(2*jj-1), 'Position', [p_r(1) p_r(2)-dh p_r(3) p_r(4)+dh]);
815 set(complexAxes(2*jj), 'Position', [p_i(1) p_i(2) p_i(3) p_i(4)+dh]);
816 end
817
818 % Process legends for stacked plots
819 if legendsOn
820 if strcmp(arrangement, 'stacked')
821 if ~isempty(legendStrR)
822 h = legend(fsax_r, fixlabel(legendStrR), 'Location', legendLoc);
823 set(h, 'FontSize', legendsFont);
824 if ~isempty(fsax_i) && ishandle(fsax_i)
825 h = legend(fsax_i, fixlabel(legendStrI), 'Location', legendLoc);
826 set(h, 'FontSize', legendsFont);
827 end
828 end
829 end
830 end
831 end % End ~isempty AOs
832
833 % Apply plot settings to the figure
834 applyPlotSettings(fsax, fsli);
835
836 % Set outputs
837 if nargout > 0
838 varargout{1} = fsfig;
839 end
840 if nargout > 1
841 varargout{2} = fsax;
842 end
843 if nargout == 3
844 varargout{3} = fsli;
845 end
846 if nargout > 3
847 error('### Too many output arguments');
848 end
849 end % End fs_plot
850
851 %--------------------------------------------------------------------------
852 % Plot tsdata and xydata objects
853 %
854 function varargout = xy_plot(varargin)
855
856 aos = varargin{1};
857 pl = varargin{2};
858 fig2plot = varargin{3};
859 Na = length(aos);
860
861 UseLatex = find(pl, 'LatexLabels');
862 if ischar(UseLatex)
863 UseLatex = eval(UseLatex);
864 end
865
866 % Extract parameters
867 arrangement = find(pl, 'Arrangement');
868 linecolors = find(pl, 'LineColors');
869 colors = find(pl, 'Colors');
870 linestyles = find(pl, 'LineStyles');
871 markers = find(pl, 'Markers');
872 linewidths = find(pl, 'LineWidths');
873 legends = find(pl, 'Legends');
874 legendsFont = find(pl, 'LegendFontSize');
875 ylabels = find(pl, 'YLabels');
876 xlabels = find(pl, 'XLabels');
877 xmaths = find(pl, 'XMaths');
878 ymaths = find(pl, 'YMaths');
879 yranges = find(pl, 'YRanges');
880 xranges = find(pl, 'XRanges');
881 yscales = find(pl, 'YScales');
882 xscales = find(pl, 'XScales');
883 type = find(pl, 'Function');
884 legendLoc = find(pl, 'LegendLocation');
885 xunits = find(pl, 'Xunits');
886 autoErrors = utils.prog.yes2true(find(pl, 'AUTOERRORS'));
887
888 % Convert the colour if it is a character to a cell-string
889 if ischar(colors)
890 colors = cellstr(colors);
891 end
892
893 % get errors
894 XerrL = find(pl, 'XerrL');
895 XerrU = find(pl, 'XerrU');
896 YerrL = find(pl, 'YerrL');
897 YerrU = find(pl, 'YerrU');
898 if ~iscell(XerrU), XerrU = {XerrU}; end
899 if ~iscell(XerrL), XerrL = {XerrL}; end
900 if ~iscell(YerrU), YerrU = {YerrU}; end
901 if ~iscell(YerrL), YerrL = {YerrL}; end
902 if (numel(XerrL) > 1 && numel(XerrL) ~= numel(aos)) || ...
903 (numel(YerrL) > 1 && numel(YerrL) ~= numel(aos)) || ...
904 (numel(XerrU) > 1 && numel(XerrU) ~= numel(aos)) || ...
905 (numel(YerrU) > 1 && numel(YerrU) ~= numel(aos))
906 error('### Please specify 1 set of errors for all AOs, or a set of errors for each AO.');
907 end
908
909 torigin = [];
910
911 % check whether we want legends or not
912 if iscell(legends)
913 legendsOn = 1;
914 else
915 if strcmpi(legends, 'off')
916 legendsOn = 0;
917 else
918 legendsOn = 1;
919 legends = [];
920 end
921 end
922
923 if ~isempty(ymaths) || ~isempty(xmaths)
924 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
925 end
926
927 if ~iscell(linewidths), linewidths = {linewidths}; end
928 if ~iscell(linestyles), linestyles = {linestyles}; end
929 if ~iscell(linecolors), linecolors = {linecolors}; end
930 if ~iscell(markers), markers = {markers}; end
931 if ~iscell(legends), legends = {legends}; end
932 if ~iscell(ylabels), ylabels = {ylabels}; end
933 if ~iscell(xlabels), xlabels = {xlabels}; end
934 if ~iscell(xmaths), xmaths = {xmaths}; end
935 if ~iscell(ymaths), ymaths = {ymaths}; end
936 if ~iscell(xranges), xranges = {xranges}; end
937 if ~iscell(yranges), yranges = {yranges}; end
938 if ~iscell(xscales), xscales = {xscales}; end
939 if ~iscell(yscales), yscales = {yscales}; end
940 if ~iscell(xunits), xunits = {xunits}; end
941
942 % collect figure handles
943 tsfig = []; tsax = []; tsli = [];
944 % Legend holder
945 legendStr = [];
946 if ~isempty(aos)
947 % Now loop over AOs to get earliest start time
948 T0 = 0;
949 if strcmp(arrangement, 'stacked')
950 T0 = 1e50;
951 for jj = 1:Na
952 % Get this AO
953 if isa(aos(jj).data, 'tsdata') && aos(jj).data.t0.utc_epoch_milli/1000 < T0
954 T0 = round(aos(jj).data.t0.utc_epoch_milli/1000);
955 end
956 end
957 end
958
959 % Do we want to use a unit placeholder on the yaxis?
960 yunits = aos(1).data.yunits;
961 yunitPlaceholder = '[Mixed]';
962 useYunitPlaceholder = false;
963 if strcmpi(arrangement, 'stacked')
964 for jj = 1:Na
965 if yunits ~= aos(jj).data.yunits
966 useYunitPlaceholder = true;
967 break;
968 end
969 end
970 end
971
972 % Do we want to use a unit placeholder on the xaxis?
973 firstXunits = aos(1).data.xunits;
974 xunitPlaceholder = '[Mixed]';
975 useXunitPlaceholder = false;
976 if strcmpi(arrangement, 'stacked')
977 for jj = 1:Na
978 if firstXunits ~= aos(jj).data.xunits
979 useXunitPlaceholder = true;
980 break;
981 end
982 end
983 end
984
985 % Now loop over AOs
986 for jj = 1:Na
987 % Get this AO
988 t0off = 0;
989
990 if useYunitPlaceholder
991 yunits = yunitPlaceholder;
992 else
993 yunits = aos(jj).data.yunits;
994 end
995
996 % what figures do we need?
997 switch arrangement
998 case 'single'
999 tsfig = [tsfig figure];
1000 tsax = subplot(1,1,1);
1001 col = colors{1};
1002 if isa(aos(jj).data, 'tsdata')
1003 torigin = aos(jj).data.t0;
1004 end
1005 case 'stacked'
1006 if ~isempty(fig2plot), tsfig = fig2plot;
1007 elseif jj==1, tsfig = figure;
1008 end
1009 tsax = subplot(1,1,1,'Parent',tsfig);
1010 col = colors{mod(jj-1,length(colors))+1};
1011 hold on;
1012 % deal with time-stamps here
1013 if isa(aos(jj).data, 'tsdata')
1014 t0off = aos(jj).data.t0.utc_epoch_milli/1000 - T0;
1015 else
1016 t0off = 0;
1017 end
1018 if isa(aos(jj).data, 'tsdata')
1019 torigin = time(T0);
1020 end
1021 case 'subplots'
1022 if ~isempty(fig2plot), tsfig = fig2plot;
1023 elseif jj==1, tsfig = figure;
1024 end
1025 tsax = [tsax subplot(Na, 1, jj,'Parent',tsfig)];
1026 col = colors{1};
1027 if isa(aos(jj).data, 'tsdata')
1028 torigin = aos(jj).data.t0;
1029 end
1030 otherwise
1031 error('### Unknown plot arrangement');
1032 end
1033
1034 %------- Apply math functions
1035
1036 % Get data and add t0 offset for this time-series
1037 x = aos(jj).data.getX + t0off;
1038 y = aos(jj).data.getY;
1039
1040 % Apply any math operations
1041 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1042 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1043
1044 % Process X units
1045 if useXunitPlaceholder
1046 xunit = xunitPlaceholder;
1047 dateTicSpec = false;
1048 else
1049 if isa(aos(jj).data, 'tsdata')
1050 xunitIn = char(aos(jj).data.xunits);
1051 xunit = parseOptions(jj, xunits, xunitIn);
1052 [x, xunit, dateTicSpec] = convertXunits(x, torigin, xunit, xunitIn);
1053 elseif isa(aos(jj).data, 'xydata')
1054 xunitIn = char(aos(jj).data.xunits);
1055 xunit = parseOptions(jj, xunits, xunitIn);
1056 dateTicSpec = false;
1057 else
1058 xunit = '';
1059 dateTicSpec = false;
1060 end
1061 end
1062
1063 % Process errors
1064 [fcn, xu, xl, yu, yl] = process_errors(jj, size(y), type, XerrU, XerrL, YerrU, YerrL, aos(jj), autoErrors);
1065
1066 %------- Plot the data
1067
1068 switch fcn
1069 case 'errorbar'
1070 li = errorbar(tsax(end), x, y, yl, yu);
1071 le = false;
1072 case type
1073 li = feval(type, tsax(end), x, y);
1074 le = false; % we have no error plots
1075 case 'errorbarxy'
1076 lhs = errorbarxy(tsax(end), x, y, xu, yu, xl, yl);
1077 li = lhs(1);
1078 le = lhs(2);
1079 end
1080 tsli = [tsli li];
1081 if isa(aos(jj).data, 'tsdata')
1082 title(sprintf('Time origin: %s', char(torigin)));
1083 end
1084
1085 %------- Add time origin to the axis handle
1086
1087 if isempty(torigin)
1088 torigin = time();
1089 end
1090
1091 set(tsax(end), 'UserData', torigin)
1092 try
1093 dcm_obj = datacursormode(get(tsfig(end),'Parent'));
1094 catch
1095 dcm_obj = datacursormode(tsfig(end));
1096 end
1097 set(dcm_obj, 'UpdateFcn', @utils.plottools.datacursormode)
1098
1099 %---------- Call datetic
1100 if dateTicSpec
1101 datetick(tsax(end), 'x', xunit(2:end-1), 'keeplimits');
1102 end
1103
1104 %------- Axis properties
1105
1106 % Set ylabel
1107 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1108 ylstr = prepareAxisLabel(yunits, ymath, ylstr, 'y', UseLatex);
1109 ylstr = fixlabel(ylstr);
1110 if UseLatex
1111 ylabel(ylstr, 'interpreter', 'latex');
1112 else
1113 ylabel(ylstr);
1114 end
1115
1116 % Set xlabel
1117 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1118 xlstr = prepareAxisLabel(xunit, xmath, xlstr, 'x', UseLatex);
1119 xlstr = fixlabel(xlstr);
1120 if UseLatex
1121 xlabel(xlstr, 'interpreter', 'latex');
1122 else
1123 xlabel(xlstr);
1124 end
1125
1126 % Set Y range
1127 yrange = parseOptions(jj, yranges, []);
1128 if ~isempty(yrange), set(tsax(end), 'YLim', yrange); end
1129
1130 % Set X range
1131 xrange = parseOptions(jj, xranges, []);
1132 if ~isempty(xrange), set(tsax(end), 'XLim', xrange); end
1133
1134 % Set Y scale
1135 yscale = parseOptions(jj, yscales, 'lin');
1136 set(tsax(end), 'YScale', yscale);
1137
1138 % Set X scale
1139 xscale = parseOptions(jj, xscales, 'lin');
1140 set(tsax(end), 'XScale', xscale);
1141
1142 % Set grid on or off
1143 grid(tsax(end), 'on');
1144
1145
1146 %------- line properties
1147 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
1148 linecolors, col, ...
1149 linestyles, '-', ...
1150 linewidths, get(0,'DefaultLineLineWidth'), ...
1151 markers, 'None');
1152
1153
1154 % Set line color
1155 set(li, 'Color', col);
1156 if ~isempty(le) && ishandle(le), set(le, 'Color', col); end
1157 % Set line style
1158 set(li, 'LineStyle', lstyle);
1159 if ishandle(le), set(le, 'LineStyle', lstyle); end
1160 % Set markers
1161 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
1162 mkr = '.';
1163 end
1164 set(li, 'Marker', mkr);
1165 % Set line widths
1166 set(li, 'LineWidth', lwidth);
1167 if ~isempty(le) && ishandle(le), set(le, 'LineWidth', lwidth); end
1168
1169 % Set legend string
1170 if legendsOn
1171 if ~isempty(aos(jj).plotinfo) && ...
1172 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1173 ~aos(jj).plotinfo.find('LEGEND_ON')
1174 for kk=1:numel(li)
1175 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1176 end
1177 else
1178 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1179 legendStr = [legendStr cellstr(lstr)];
1180 % Set the legend now if we can
1181 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
1182 legend(fixlabel(legendStr{end}), 'Location', legendLoc);
1183 end
1184 end
1185 end
1186 end
1187
1188 % Process legends for stacked plots
1189 if legendsOn
1190 if strcmp(arrangement, 'stacked')
1191 if ~isempty(legendStr)
1192 h = legend(fixlabel(legendStr), 'Location', legendLoc);
1193 set(h, 'FontSize', legendsFont);
1194 end
1195 end
1196 end
1197 end % End if empty AOs
1198
1199 % Apply plot settings to the figure
1200 applyPlotSettings(tsax, tsli);
1201
1202 % Set outputs
1203 if nargout > 0
1204 varargout{1} = tsfig;
1205 end
1206 if nargout > 1
1207 varargout{2} = tsax;
1208 end
1209 if nargout == 3
1210 varargout{3} = tsli;
1211 end
1212 if nargout > 3
1213 error('### Too many output arguments');
1214 end
1215 end % end xy_plot
1216
1217
1218 %--------------------------------------------------------------------------
1219 % Plot cdata objects
1220 %
1221 function varargout = y_plot(varargin)
1222
1223 aos = varargin{1};
1224 pl = varargin{2};
1225 fig2plot = varargin{3};
1226
1227 UseLatex = find(pl, 'LatexLabels');
1228 if ischar(UseLatex)
1229 UseLatex = eval(UseLatex);
1230 end
1231
1232 % Extract parameters
1233 arrangement = find(pl, 'Arrangement');
1234 linecolors = find(pl, 'LineColors');
1235 colors = find(pl, 'Colors');
1236 linestyles = find(pl, 'LineStyles');
1237 markers = find(pl, 'Markers');
1238 linewidths = find(pl, 'LineWidths');
1239 legends = find(pl, 'Legends');
1240 legendsFont = find(pl, 'LegendFontSize');
1241 ylabels = find(pl, 'YLabels');
1242 xlabels = find(pl, 'XLabels');
1243 xmaths = find(pl, 'XMaths');
1244 ymaths = find(pl, 'YMaths');
1245 yranges = find(pl, 'YRanges');
1246 xranges = find(pl, 'XRanges');
1247 yscales = find(pl, 'YScales');
1248 xscales = find(pl, 'XScales');
1249 type = find(pl, 'Function');
1250 legendLoc = find(pl, 'LegendLocation');
1251 autoErrors = find(pl, 'AUTOERRORS');
1252
1253 % Convert the colour if it is a character to a cell-string
1254 if ischar(colors)
1255 colors = cellstr(colors);
1256 end
1257
1258 % get errors
1259 YerrL = find(pl, 'YerrL');
1260 YerrU = find(pl, 'YerrU');
1261 if ~iscell(YerrU), YerrU = {YerrU}; end
1262 if ~iscell(YerrL), YerrL = {YerrL}; end
1263 if (numel(YerrL) > 1 && numel(YerrL) ~= numel(aos)) || ...
1264 (numel(YerrU) > 1 && numel(YerrU) ~= numel(aos))
1265 error('### Please specify 1 set of errors for all AOs, or a set of errors for each AO.');
1266 end
1267
1268 % check whether we want legends or not
1269 if iscell(legends)
1270 legendsOn = 1;
1271 else
1272 if strcmp(legends, 'off')
1273 legendsOn = 0;
1274 else
1275 legendsOn = 1;
1276 legends = [];
1277 end
1278 end
1279
1280 if ~isempty(ymaths) || ~isempty(xmaths)
1281 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
1282 end
1283
1284 if ~iscell(linewidths), linewidths = {linewidths}; end
1285 if ~iscell(linestyles), linestyles = {linestyles}; end
1286 if ~iscell(linecolors), linecolors = {linecolors}; end
1287 if ~iscell(markers), markers = {markers}; end
1288 if ~iscell(legends), legends = {legends}; end
1289 if ~iscell(ylabels), ylabels = {ylabels}; end
1290 if ~iscell(xlabels), xlabels = {xlabels}; end
1291 if ~iscell(xmaths), xmaths = {xmaths}; end
1292 if ~iscell(ymaths), ymaths = {ymaths}; end
1293 if ~iscell(xranges), xranges = {xranges}; end
1294 if ~iscell(yranges), yranges = {yranges}; end
1295 if ~iscell(xscales), xscales = {xscales}; end
1296 if ~iscell(yscales), yscales = {yscales}; end
1297
1298 % collect figure handles
1299 cfig = []; cax = []; cli = [];
1300 % Legend holder
1301 legendStr = [];
1302 if ~isempty(aos)
1303
1304 % Now loop over AOs
1305 Na = length(aos);
1306
1307 % Do we want to use a unit placeholder on the yaxis?
1308 yunits = aos(1).data.yunits;
1309 yunitPlaceholder = '[Mixed]';
1310 useYunitPlaceholder = false;
1311 if strcmpi(arrangement, 'stacked')
1312 for jj = 1:Na
1313 if yunits ~= aos(jj).data.yunits
1314 useYunitPlaceholder = true;
1315 break;
1316 end
1317 end
1318 end
1319
1320 for jj = 1:Na
1321 if useYunitPlaceholder
1322 yunits = yunitPlaceholder;
1323 else
1324 yunits = aos(jj).data.yunits;
1325 end
1326
1327 % what figures do we need?
1328 switch arrangement
1329 case 'single'
1330 cfig = [cfig figure];
1331 cax = subplot(1,1,1);
1332 col = colors{1};
1333 case 'stacked'
1334 if ~isempty(fig2plot), cfig = fig2plot;
1335 elseif jj==1, cfig = figure;
1336 end
1337 % if jj==1, cfig = figure; end
1338 cax = subplot(1,1,1,'Parent',cfig);
1339 col = colors{mod(jj-1,length(colors))+1};
1340 hold on;
1341 case 'subplots'
1342 if ~isempty(fig2plot), cfig = fig2plot;
1343 elseif jj==1, cfig = figure;
1344 end
1345 % if jj == 1, cfig = figure; end
1346 cax = [cax subplot(Na, 1, jj)];
1347 col = colors{1};
1348 otherwise
1349 error('### Unknown plot arrangement');
1350 end
1351
1352 % Get data
1353 if isreal(aos(jj).data.getY)
1354 x = 1:length(aos(jj).data.getY);
1355 y = aos(jj).data.getY;
1356 else
1357 x = real(aos(jj).data.getY);
1358 y = imag(aos(jj).data.getY);
1359 end
1360
1361 %------- Apply math functions
1362 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1363 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1364 % Process errors
1365 [fcn, xu, xl, yu, yl] = process_errors(jj, size(y), type, {[]}, {[]}, YerrU, YerrL, aos(jj), autoErrors);
1366
1367 %------- Plot the data
1368 switch fcn
1369 case 'errorbar'
1370 lhs = errorbarxy(cax(end), x, y,zeros(size(yl)),yu,zeros(size(yl)),yl);
1371 idcs = lhs(1);
1372 le = lhs(2);
1373 case type
1374 idcs = feval(type, cax(end), x, y);
1375 le = false; % we have no error plots
1376 case 'errorbarxy'
1377 lhs = errorbarxy(cax(end), x, y, xu, yu, xl, yl);
1378 idcs = lhs(1);
1379 le = lhs(2);
1380 end
1381 %------- Plot the data
1382 % idcs = feval(type, cax(end), x, y);
1383 % cli = [cli idcs(1:end).'];
1384
1385 %------- Axis properties
1386
1387 % Set ylabel
1388 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1389 ylstr = prepareAxisLabel(yunits, ymath, ylstr, 'y', UseLatex);
1390 ylstr = fixlabel(ylstr);
1391 if UseLatex
1392 ylabel(ylstr, 'interpreter', 'latex');
1393 else
1394 ylabel(ylstr);
1395 end
1396
1397 % Set xlabel
1398 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1399 xlstr = prepareAxisLabel(unit('Index'), xmath, xlstr, 'x', UseLatex);
1400 xlstr = fixlabel(xlstr);
1401 if UseLatex
1402 xlabel(xlstr, 'interpreter', 'latex');
1403 else
1404 xlabel(xlstr);
1405 end
1406
1407 % Set Y scale
1408 yscale = parseOptions(jj, yscales, 'lin');
1409 set(cax(end), 'YScale', yscale);
1410
1411 % Set X scale
1412 xscale = parseOptions(jj, xscales, 'lin');
1413 set(cax(end), 'XScale', xscale);
1414
1415 % Set Y range
1416 yrange = parseOptions(jj, yranges, []);
1417 if ~isempty(yrange), set(cax(end), 'YLim', yrange); end
1418
1419 % Set X range
1420 xrange = parseOptions(jj, xranges, []);
1421 if ~isempty(xrange), set(cax(end), 'XLim', xrange); end
1422
1423 % Set grid on or off
1424 grid(cax(end), 'on');
1425
1426 %------- line properties
1427
1428 [col, lstyle, lwidth, mkr] = parseLineProps(jj, aos(jj).plotinfo, ...
1429 linecolors, col, ...
1430 linestyles, '-', ...
1431 linewidths, get(0,'DefaultLineLineWidth'), ...
1432 markers, 'None');
1433
1434 % Overide line colors with user defined colors
1435 set(idcs, 'Color', col);
1436 if ~isempty(le) && ishandle(le), set(le, 'Color', col); end
1437
1438 % Set line style
1439 set(idcs, 'LineStyle', lstyle);
1440 if ishandle(le), set(le, 'LineStyle', lstyle); end
1441 % Set Markers
1442 if numel(x) == 1 && numel(y) == 1 && strcmp(mkr, 'None')
1443 mkr = '.';
1444 end
1445 set(idcs, 'Marker', mkr);
1446 % Set line widths
1447 set(idcs, 'LineWidth', lwidth);
1448 if ~isempty(le) && ishandle(le), set(le, 'LineWidth', lwidth); end
1449
1450 % Set legend string
1451 if legendsOn
1452 if ~isempty(aos(jj).plotinfo) && ...
1453 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1454 ~aos(jj).plotinfo.find('LEGEND_ON')
1455 for kk=1:numel(li)
1456 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1457 end
1458 else
1459 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1460 legendStr = [legendStr cellstr(lstr)];
1461 % Set the legend now if we can
1462 if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
1463 legend(fixlabel(legendStr{end}), 'Location', legendLoc);
1464 end
1465 end
1466 end
1467 end % End AO loop
1468
1469 % Process legends for stacked plots
1470 if legendsOn
1471 if strcmp(arrangement, 'stacked')
1472 if ~isempty(legendStr)
1473 h = legend(fixlabel(legendStr), 'Location', legendLoc);
1474 set(h, 'FontSize', legendsFont);
1475 end
1476 end
1477 end
1478
1479 end
1480
1481 % Apply plot settings to the figure
1482 applyPlotSettings(cax, cli);
1483
1484 % Set outputs
1485 if nargout > 0
1486 varargout{1} = cfig;
1487 end
1488 if nargout > 1
1489 varargout{2} = cax;
1490 end
1491 if nargout == 3
1492 varargout{3} = cli;
1493 end
1494 if nargout > 3
1495 error('### Too many output arguments');
1496 end
1497 end % End y_plot
1498
1499 %--------------------------------------------------------------------------
1500 % Plot xyzdata objects
1501 %
1502 function varargout = xyz_plot(varargin)
1503
1504 aos = varargin{1};
1505 pl = varargin{2};
1506 fig2plot = varargin{3};
1507
1508 UseLatex = find(pl, 'LatexLabels');
1509 if ischar(UseLatex)
1510 UseLatex = eval(UseLatex);
1511 end
1512
1513 % Extract parameters
1514 arrangement = find(pl, 'Arrangement');
1515 legends = find(pl, 'Legends');
1516 legendsFont = find(pl, 'LegendFontSize');
1517 zlabels = find(pl, 'ZLabels');
1518 ylabels = find(pl, 'YLabels');
1519 xlabels = find(pl, 'XLabels');
1520 xmaths = find(pl, 'XMaths');
1521 ymaths = find(pl, 'YMaths');
1522 zmaths = find(pl, 'ZMaths');
1523 legendLoc = find(pl, 'LegendLocation');
1524 yranges = find(pl, 'YRanges');
1525 xranges = find(pl, 'XRanges');
1526 zranges = find(pl, 'ZRanges');
1527 zscales = find(pl, 'ZScales');
1528 yscales = find(pl, 'YScales');
1529 xscales = find(pl, 'XScales');
1530 invertY = find(pl, 'InvertY');
1531
1532 % check whether we want legends or not
1533 if iscell(legends)
1534 legendsOn = 1;
1535 else
1536 if strcmp(legends, 'off')
1537 legendsOn = 0;
1538 else
1539 legendsOn = 1;
1540 legends = [];
1541 end
1542 end
1543
1544 if ~isempty(ymaths) || ~isempty(xmaths)
1545 warning('The use of the ''ymaths'' and ''xmaths'' parameters is deprecated. Please perform any calculations before calling iplot.');
1546 end
1547
1548 if ~iscell(legends), legends = {legends}; end
1549 if ~iscell(ylabels), ylabels = {ylabels}; end
1550 if ~iscell(xlabels), xlabels = {xlabels}; end
1551 if ~iscell(zlabels), zlabels = {zlabels}; end
1552 if ~iscell(xmaths), xmaths = {xmaths}; end
1553 if ~iscell(ymaths), ymaths = {ymaths}; end
1554 if ~iscell(zmaths), zmaths = {zmaths}; end
1555 if ~iscell(xranges), xranges = {xranges}; end
1556 if ~iscell(yranges), yranges = {yranges}; end
1557 if ~iscell(zranges), zranges = {zranges}; end
1558 if ~iscell(xscales), xscales = {xscales}; end
1559 if ~iscell(yscales), yscales = {yscales}; end
1560 if ~iscell(zscales), zscales = {zscales}; end
1561
1562
1563 % collect figure handles
1564 tdfig = [];
1565 tdax = [];
1566 tdli = [];
1567
1568 % Legend holder
1569 legendStr = [];
1570
1571 if ~isempty(aos)
1572
1573 % Now loop over AOs
1574 Na = length(aos);
1575 for jj = 1:Na
1576 % what figures do we need?
1577 switch arrangement
1578 case 'single'
1579 tdfig = [tdfig figure];
1580 tdax = subplot(1,1,1);
1581 case 'subplots'
1582 if ~isempty(fig2plot), tdfig = fig2plot;
1583 elseif jj==1, tdfig = figure;
1584 end
1585 % if jj == 1, tdfig = figure; end
1586 tdax = [tdax subplot(Na, 1, jj)];
1587 otherwise
1588 warning('!!! Plot arrangement ''%s'' not supported on XYZ plots. Using ''single'' instead.', arrangement);
1589 arrangment = 'single';
1590 tdfig = [tdfig figure];
1591 tdax = subplot(1,1,1);
1592 end
1593
1594 %------- Apply math functions
1595 x = aos(jj).data.x;
1596 y = aos(jj).data.getY;
1597 z = aos(jj).data.z;
1598
1599 ymath = parseOptions(jj, ymaths, 'y'); eval(sprintf('y = %s;', ymath));
1600 xmath = parseOptions(jj, xmaths, 'x'); eval(sprintf('x = %s;', xmath));
1601 zmath = parseOptions(jj, zmaths, 'z'); eval(sprintf('z = %s;', zmath));
1602
1603 %------- Plot the data
1604
1605 idcs = pcolor(x,y,z);
1606 tdli = [tdli idcs(1:end).'];
1607
1608 % plot properties
1609 set(idcs, 'EdgeColor', 'none');
1610
1611 %------- Axis properties
1612
1613 % Reverse y-direction for spectrograms
1614 if invertY
1615 set(tdax(end), 'YDir', 'reverse');
1616 end
1617
1618 % Set ylabel
1619 ylstr = parseOptions(jj, ylabels, find(pl, 'YLabels'));
1620 ylstr = prepareAxisLabel(aos(jj).data.yunits, ymath, ylstr, 'y', UseLatex);
1621 ylstr = fixlabel(ylstr);
1622 if UseLatex
1623 ylabel(ylstr, 'interpreter', 'latex');
1624 else
1625 ylabel(ylstr);
1626 end
1627
1628 % Set xlabel
1629 xlstr = parseOptions(jj, xlabels, find(pl, 'XLabels'));
1630 xlstr = prepareAxisLabel(aos(jj).data.xunits, xmath, xlstr, 'x', UseLatex);
1631 xlstr = fixlabel(xlstr);
1632 if UseLatex
1633 xlabel(xlstr, 'interpreter', 'latex');
1634 else
1635 xlabel(xlstr);
1636 end
1637
1638 % Set grid on or off
1639 grid(tdax(end), 'on');
1640
1641 % Set title string
1642 if legendsOn
1643 if ~isempty(aos(jj).plotinfo) && ...
1644 aos(jj).plotinfo.isparam('LEGEND_ON') && ...
1645 ~aos(jj).plotinfo.find('LEGEND_ON')
1646 for kk=1:numel(li)
1647 set(get(get(li(kk),'Annotation'),'LegendInformation'),'IconDisplayStyle','off'); % Exclude line from legend
1648 end
1649 else
1650 lstr = parseOptions(jj, legends, makeLegendStr(aos(jj)));
1651 legendStr = [legendStr cellstr(lstr)];
1652 % Set the legend now if we can
1653 title(legendStr{end});
1654 end
1655 end
1656
1657 % Set colorbars
1658 hc = colorbar('peer', tdax(end));
1659 zlstr = parseOptions(jj, zlabels, find(pl, 'Zlabels'));
1660 zlstr = prepareAxisLabel(aos(jj).data.zunits, zmath, zlstr, 'z', UseLatex);
1661 zlstr = fixlabel(zlstr);
1662 ylh = get(hc, 'YLabel');
1663 set(ylh, 'String', zlstr);
1664 set(ylh, 'Fontsize', get(tdax(end), 'Fontsize'))
1665 set(ylh, 'FontName', get(tdax(end), 'FontName'))
1666 set(ylh, 'FontAngle', get(tdax(end), 'FontAngle'))
1667 set(ylh, 'FontWeight', get(tdax(end), 'FontWeight'))
1668
1669
1670 % Set Y scale
1671 yscale = parseOptions(jj, yscales, 'lin');
1672 set(tdax(end), 'YScale', yscale);
1673
1674 % Set X scale
1675 xscale = parseOptions(jj, xscales, 'lin');
1676 set(tdax(end), 'XScale', xscale);
1677
1678 % Set Z scale
1679 zscale = parseOptions(jj, zscales, 'lin');
1680 set(tdax(end), 'ZScale', zscale);
1681
1682 % Set Y range
1683 yrange = parseOptions(jj, yranges, []);
1684 if ~isempty(yrange), set(tdax(end), 'YLim', yrange); end
1685
1686 % Set X range
1687 xrange = parseOptions(jj, xranges, []);
1688 if ~isempty(xrange), set(tdax(end), 'XLim', xrange); end
1689
1690 % Set Z range
1691 zrange = parseOptions(jj, zranges, []);
1692 if ~isempty(zrange), set(tdax(end), 'CLim', zrange); end
1693 end
1694 end
1695
1696 % Apply plot settings to the figure
1697 applyPlotSettings(tdax, tdli);
1698
1699 % Set outputs
1700 if nargout > 0
1701 varargout{1} = tdfig;
1702 end
1703 if nargout > 1
1704 varargout{2} = tdax;
1705 end
1706 if nargout == 3
1707 varargout{3} = tdli;
1708 end
1709 if nargout > 3
1710 error('### Too many output arguments');
1711 end
1712 end % end xyz_plot
1713
1714 %--------------------------------------------------------------------------
1715 % Get Info Object
1716 %--------------------------------------------------------------------------
1717 function ii = getInfo(varargin)
1718 if nargin == 1 && strcmpi(varargin{1}, 'None')
1719 sets = {};
1720 pl = [];
1721 elseif nargin == 1&& ~isempty(varargin{1}) && ischar(varargin{1})
1722 sets{1} = varargin{1};
1723 pl = getDefaultPlist(sets{1});
1724 else
1725 sets = {'Time-series Plot', 'Frequency-series Plot', 'Y Data Plot', 'X-Y Data Plot', '3D Plot'};
1726 % get plists
1727 pl(size(sets)) = plist;
1728 for k = 1:numel(sets)
1729 pl(k) = getDefaultPlist(sets{k});
1730 end
1731 end
1732 % Build info object
1733 ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.output, '$Id: iplot.m,v 1.142 2011/08/15 06:08:28 hewitson Exp $', sets, pl);
1734 ii.setModifier(false);
1735 ii.setOutmin(0);
1736 end
1737
1738 % Parse line properties from plist, or defaults
1739 function [col, lstyle, lwidth, mkr] = parseLineProps(jj, pli, ...
1740 linecolors, dcol, ...
1741 linestyles, dlstyle, ...
1742 linewidths, dlwidth, ...
1743 markers, dmkr)
1744
1745 if isempty(pli)
1746 pli = plist;
1747 end
1748
1749 % Set line color but overide with user colors
1750 col = pli.find('color');
1751 if isempty(col)
1752 col = parseOptions(jj, linecolors, dcol);
1753 end
1754
1755 % Set line style
1756 lstyle = pli.find('linestyle');
1757 if isempty(lstyle)
1758 lstyle = parseOptions(jj, linestyles, dlstyle);
1759 end
1760
1761 % Set line widths
1762 lwidth = pli.find('linewidth');
1763 if isempty(lwidth)
1764 lwidth = parseOptions(jj, linewidths, dlwidth);
1765 end
1766
1767 % Set markers
1768 mkr = pli.find('marker');
1769 if isempty(mkr)
1770 mkr = parseOptions(jj, markers, dmkr);
1771 end
1772
1773 end
1774
1775
1776 %--------------------------------------------------------------------------
1777 % Get Default Plist
1778 %--------------------------------------------------------------------------
1779 function plout = getDefaultPlist(set)
1780 persistent pl;
1781 persistent lastset;
1782 if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
1783 pl = buildplist(set);
1784 lastset = set;
1785 end
1786 pl.pset('LEGENDFONTSIZE', LTPDAprefs.legendFontSize);
1787 plout = pl;
1788 end
1789
1790 function out = buildplist(set)
1791
1792 % Get the LTPDA color set for lines
1793 colors = getappdata(0,'ltpda_default_plot_colors');
1794
1795 out = plist();
1796
1797 % Figure
1798 p = param({'Figure',['The handle of the figure to plot in to. This will be ignored if the AOs to plot are inconsistent,<br>'...
1799 'containing different class of data (such as tsdata and fsdata), or if the ''arrangement''<br>',...
1800 'parameter is passed as ''single''.']}, paramValue.EMPTY_DOUBLE);
1801 out.append(p);
1802
1803 % Colors
1804 p = param({'Colors', 'A list of colors which will be cycled through for each line in a plot.'}, colors);
1805 out.append(p);
1806
1807 % Arrangement
1808 p = param({'Arrangement',['Select the plot layout:<ul>',...
1809 '<li>''single'' - plot all AOs on individual figures</li>',...
1810 '<li>''stacked'' - plot all AOs on the same axes</li>',...
1811 '<li>''subplots'' - plot all AOs on subplots</li>'...
1812 '</ul>']}, {1, {'stacked', 'single', 'subplots'}, paramValue.SINGLE});
1813 out.append(p);
1814
1815 % Function
1816 p = param({'Function',['Specify the plot function:<ul>',...
1817 '<li>''plot''</li>', ...
1818 '<li>''stairs''</li>',...
1819 '<li>''stem''</li>',...
1820 '</ul>'...
1821 '[*** doesn''t work for xyzdata AOs]']}, {1, {'plot', 'stairs', 'stem'}, paramValue.SINGLE});
1822 out.append(p);
1823
1824 % LineColors
1825 p = param({'LineColors', ['A cell-array of color definitions, one for each trace.<br>'...
1826 'Give an empty string to use the default color.']}, ...
1827 {1, {''}, paramValue.OPTIONAL});
1828 out.append(p);
1829
1830 % LineColors
1831 p = param({'LineStyles', ['A cell-array of line styles, one for each trace.<br>'...
1832 'Give an empty string to use the default style.']}, ...
1833 {1, {''}, paramValue.OPTIONAL});
1834 out.append(p);
1835
1836 % Markers
1837 p = param({'Markers', ['A cell-array of markers, one for each trace.']}, ...
1838 {1, {''}, paramValue.OPTIONAL});
1839 out.append(p);
1840
1841 % LineWidths
1842 p = param({'LineWidths', ['A cell-array of line widths, one for each trace.<br>'...
1843 'Give an empty string to use the default line width.']}, ...
1844 {1, {''}, paramValue.OPTIONAL});
1845 out.append(p);
1846
1847 % Legends
1848 p = param({'Legends', ['Give a cell-array of strings to be used for<br>'...
1849 'the plot legends. If a cell contains an empty<br>'...
1850 'string, the default legend string is built.<br>'...
1851 'If a single string ''off'' is given instead of a<br>'...
1852 'cell-array, then the legends are all switched off.']}, ...
1853 {1, {''}, paramValue.OPTIONAL});
1854 out.append(p);
1855
1856 % LegendLocation
1857 p = param({'LegendLocation','Choose the legend location.'}, ...
1858 {5, {'North', 'South', 'East', 'West', ...
1859 'NorthEast', 'NorthWest', 'SouthEast', 'SouthWest', ...
1860 'NorthOutside', 'SouthOutside', 'EastOutside', 'WestOutside', ...
1861 'NorthEastOutside', 'NorthWestOutside', 'SouthEastOutside', ...
1862 'SouthWestOutside', 'Best', 'BestOutside'}, paramValue.SINGLE});
1863 out.append(p);
1864
1865 % LegendFontSize
1866 p = param({'LegendFontSize','Choose the legend font size.'}, ...
1867 {1, {LTPDAprefs.legendFontSize}, paramValue.SINGLE});
1868 out.append(p);
1869
1870 % XerrL
1871 p = param({'XerrL','Lower bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1872 out.append(p);
1873
1874 % XerrU
1875 p = param({'XerrU','Upper bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1876 out.append(p);
1877
1878 % YerrL
1879 p = param({'YerrL','Lower bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1880 out.append(p);
1881
1882 % YerrU
1883 p = param({'YerrU','Upper bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1884 out.append(p);
1885
1886 % XScales
1887 p = param({'XScales', ['A cell-array specifying the scale to be used on each x-axis.<br>'...
1888 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1889 out.append(p);
1890
1891 % YScales
1892 p = param({'YScales', ['A cell-array specifying the scale to be used on each y-axis.<br>'...
1893 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1894 out.append(p);
1895
1896 % XRanges
1897 p = param({'XRanges', ['A cell-array specifying the ranges to be displayed on each x-axis.<br>'...
1898 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1899 out.append(p);
1900
1901 % YRanges
1902 p = param({'YRanges', ['A cell-array specifying the ranges to be displayed on each y-axis.<br>'...
1903 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1904 out.append(p);
1905
1906 % LatexLabels
1907 p = param({'LatexLabels','Use latex interpreter for axis labels.'}, paramValue.TRUE_FALSE);
1908 p.val.setValIndex(2);
1909 out.append(p);
1910
1911 % YMaths
1912 p = param({'YMaths',['Specify math operations to perform on the data vector ''y''. [DEPRECATED]<br>',...
1913 'For example, <tt>plist(''Ymaths'', ''sqrt(y)'')</tt>.']}, paramValue.EMPTY_STRING);
1914 out.append(p);
1915
1916
1917 % No auto-errors
1918 p = param({'AUTOERRORS',['If the AO contains errors, they will be plotted. You can avoid plotting the <br>',...
1919 'errors by setting this to false.']}, paramValue.FALSE_TRUE);
1920 out.append(p);
1921
1922 switch lower(set)
1923 case 'frequency-series plot'
1924 % ComplexPlotType
1925 p = param({'complexPlotType',['Specify how to plot complex data. Choose from:<ul>',...
1926 '<li>''realimag''</li>',...
1927 '<li>''absdeg''</li>',...
1928 '<li>''absrad''</li>'...
1929 '</ul>']}, {1, {'absdeg', 'realimag', 'absrad'}, paramValue.SINGLE});
1930 out.append(p);
1931
1932 % Xlabel
1933 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1934 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1935 out.append(p);
1936 % ylabels
1937 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1938 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE(''));
1939 out.append(p);
1940
1941 % XMaths
1942 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1943 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1944 out.append(p);
1945
1946 case 'time-series plot'
1947
1948 % Xlabel
1949 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1950 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1951 out.append(p);
1952
1953 % Ylabels
1954 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1955 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
1956 out.append(p);
1957
1958 % Xunits
1959 p = param({'Xunits', ['Specify the units of time on the x-axis as<ul>'...
1960 '<li>''us'' - microseconds<li>' ...
1961 '<li>''ms'' - milliseconds<li>' ...
1962 '<li>''s'' - seconds<li>' ...
1963 '<li>''m'' - minutes<li>' ...
1964 '<li>''h'' - hours<li>' ...
1965 '<li>''D'' - days<li>' ...
1966 '<li>''M'' - months<li>' ...
1967 '<li>''HH:MM:SS'' - using a date/time format</li>' ...
1968 '</ul>']}, {3, {'us', 'ms', 's', 'm', 'h', 'D', 'M', 'HH:MM:SS', 'yyyy-mm-dd HH:MM:SS'}, paramValue.OPTIONAL});
1969 out.append(p);
1970
1971 case 'x-y data plot'
1972 % Xlabel
1973 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1974 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('X-data'));
1975 out.append(p);
1976
1977 % Ylabels
1978 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1979 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Y-data'));
1980 out.append(p);
1981
1982 % XMaths
1983 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1984 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1985 out.append(p);
1986
1987 case '3d plot'
1988
1989 out.pset('arrangement', 'single');
1990
1991 % Xlabel
1992 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1993 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1994 out.append(p);
1995
1996 % Ylabels
1997 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1998 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1999 out.append(p);
2000
2001 % Zlabels
2002 p = param({'ZLabels',['Specify the labels to be used on the z-axes. The units are added from<br>',...
2003 'the data object ''zunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
2004 out.append(p);
2005
2006 % XMaths
2007 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
2008 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
2009 out.append(p);
2010
2011 % ZMaths
2012 p = param({'ZMaths',['Specify math operations to perform on the data vector ''z''. [DEPRECATED]<br>',...
2013 'For example, <tt>plist(''Zmaths'', ''abs(z)'')</tt>.']}, paramValue.EMPTY_STRING);
2014 out.append(p);
2015
2016 % ZScales
2017 p = param({'ZScales', ['A cell-array specifying the scale to be used on each z-axis.<br>'...
2018 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
2019 out.append(p);
2020
2021 % ZRanges
2022 p = param({'ZRanges', ['A cell-array specifying the ranges to be displayed on each z-axis.<br>'...
2023 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
2024 out.append(p);
2025
2026 % Invert y-axis
2027 p = param({'InvertY', ['Invert the y-axis or not.']}, paramValue.TRUE_FALSE);
2028 out.append(p);
2029
2030 out.remove('linestyles');
2031 out.remove('linewidths');
2032 out.remove('linecolors');
2033 out.remove('markers');
2034
2035 case 'y data plot'
2036 % Xlabel
2037 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
2038 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Sample'));
2039 out.append(p);
2040
2041 % Ylabels
2042 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
2043 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Value'));
2044 out.append(p);
2045 otherwise
2046 error('### Unknown set [%s]', set);
2047 end
2048 end
2049
2050
2051 function name = makeLegendStr(a)
2052
2053 name = utils.plottools.label(a.name);
2054 desc = utils.plottools.label(a.description);
2055
2056 if isempty(name)
2057 name = '?';
2058 end
2059
2060 if ~isempty(desc) && LTPDAprefs.includeDescription
2061 name = [name ': ' desc];
2062 end
2063
2064
2065 end
2066
2067 % Perform some substitutions on the labels
2068 function ss = fixlabel(ss)
2069
2070 MAX_LENGTH = 100;
2071 wasCell = true;
2072 if ~iscell(ss)
2073 ss = {ss};
2074 wasCell = false;
2075 end
2076
2077 for kk = 1:numel(ss)
2078 s = ss{kk};
2079 if ~isempty(s)
2080 % Replace all ^(...) with ^{...}
2081 jj = 1;
2082 while jj < numel(s)
2083 if strcmp(s(jj:jj+1), '^(')
2084 % find next )
2085 for k = 1:numel(s)-jj+1
2086 if s(jj+k) == ')'
2087 s(jj+1) = '{';
2088 s(jj+k) = '}';
2089 break;
2090 end
2091 end
2092 end
2093 jj = jj + 1;
2094 end
2095 % Replace all .^ with ^
2096 s = strrep(s, '.^', '^');
2097
2098 % reduce size
2099 if length(s) > MAX_LENGTH
2100 s = s(1:MAX_LENGTH-3);
2101 if s(end) == '\'
2102 s = s(1:end-1)
2103 end
2104 s = [ s '...' ];
2105 end
2106
2107 end
2108 ss(kk) = {s};
2109 end
2110
2111 if ~wasCell
2112 ss = ss{1};
2113 end
2114
2115 end
2116
2117 %-----------------------------------------------
2118 % Change X data for time-series according to the specified xunits
2119 function [x, xunit, dateTicSpec] = convertXunits(x, t0, xunit, xunitIn)
2120
2121 dateTicSpec = false;
2122
2123 xunit = strtrim(xunit);
2124 xunitIn = strtrim(xunitIn);
2125 if ~strcmpi(strtrim(xunitIn), '[s]')
2126 warning('### I can only convert from [s] to %s - ignoring requested Xunit', xunit);
2127 xunit = xunitIn;
2128 else
2129 switch strtrim(xunit)
2130 case {'[us]', 'us'}
2131 x = x .* 1e6;
2132 case {'[ms]', 'ms'}
2133 x = x .* 1e3;
2134 case {'[s]', 's'}
2135 case {'[m]', 'm'}
2136 x = x ./ 60;
2137 case {'[h]', 'h'}
2138 x = x ./ 3600;
2139 case {'[D]', 'D'}
2140 x = x ./ 86400;
2141 otherwise
2142 % then we have a datetic spec
2143 dateTicSpec = true;
2144 % first convert x data to serial date
2145 st = format(t0, 'yyyy-mm-dd hh:mm:ss');
2146 st = regexp(st, ' ', 'split');
2147 st = [st{1} ' ' st{2}];
2148 t0 = datenum(st); % get t0 as a serial date
2149 x = t0 + x./86400; % convert x to days
2150 end
2151 end
2152 if xunit(1) ~= '['
2153 xunit = ['[' xunit];
2154 end
2155 if xunit(end) ~= ']'
2156 xunit = [xunit ']'];
2157 end
2158 % 'us' - microseconds
2159 % 'ms' - milliseconds
2160 % 's' - seconds [default]
2161 % 'm' - minutes
2162 % 'h' - hours
2163 % 'D' - days
2164 % 'M' - months
2165 % 'HH:MM:SS' - using a date/time format
2166
2167 end
2168
2169 %----------------------------------------
2170 % Prepare an axis label
2171 function lstr = prepareAxisLabel(units, math, lstr, axis, UseLatex)
2172 if isa(units, 'unit')
2173
2174 if ismac && UseLatex
2175 units = units.tolabel;
2176 else
2177 units = {fixlabel(char(units))};
2178 end
2179 else
2180 units = {units};
2181 end
2182 if ~isempty(math)
2183 if ~isempty(lstr)
2184 lstr = strrep(math, axis, lstr);
2185 end
2186 lstr = [fixlabel(lstr) ' ' units{1} ];
2187 else
2188 lstr = [fixlabel(lstr) ' ' units{1}];
2189 end
2190 end
2191
2192 % Parse cell-array of options
2193 function opt = parseOptions(varargin) %jj, opts, dopt
2194
2195 jj = varargin{1};
2196 opts = varargin{2};
2197 dopt = varargin{3};
2198 opt = dopt;
2199
2200 if ~iscell(opts)
2201 opts = {opts};
2202 end
2203 Nopts = numel(opts);
2204
2205 % First look for the 'all' keyword
2206 if Nopts == 2 && strcmpi(opts{1}, 'all')
2207 opt = opts{2};
2208 else
2209 if jj <= Nopts && ~isempty(opts{jj})
2210 opt = opts{jj};
2211 end
2212 end
2213
2214 end
2215
2216
2217
2218 % ERRORBARXY Customizable error bar plot in X and Y direction
2219 %
2220 % This function allows the user to plot the graph of x against y, along with
2221 % both x and y errorbars.
2222 %
2223 % With 4 numeric arguments (x,y,dx,dy), error bar are assumed to be of
2224 % same magnitude in both direction.
2225 %
2226 % One can specify lower and upper error bar with 6 numeric arguments
2227 % (x,y,dx_high,dy_high,dx_low,dy_low).
2228 %
2229 % x,y,dx,dy,... must be vectors of the same length
2230 %
2231 % [hp he] = errorbarxy(...) returns respectively the handle for the line
2232 % plot object and the line error bar object.
2233 %
2234 % It is possible to customize the line properties of the error bars by
2235 % adding pair of 'field/value' fields (such as 'LineWidth',2) that can be
2236 % understood by line. See LineProperties for more information.
2237 %
2238 % --------
2239 % EXAMPLES
2240 % --------
2241 % X = 10 * rand(7,1);
2242 % Y = 10 * rand(7,1);
2243 % dx = rand(7,1);
2244 % dy = rand(7,1);
2245 % errorbarxy(X,Y,dx,dy,'Color','k','LineStyle','none','Marker','o',...
2246 % 'MarkerFaceColor','w','LineWidth',1,'MarkerSize',11);
2247 %
2248 % X = 10 * rand(7,1);
2249 % Y = 10 * rand(7,1);
2250 % dx = rand(7,1);
2251 % dy = rand(7,1);
2252 % dx2 = rand(7,1);
2253 % dy2 = rand(7,1);
2254 % errorbarxy(X,Y,dx,dy,dx2,dy2,'Color','B','LineStyle','--','Marker','s',...
2255 % 'MarkerFaceColor','w','LineWidth',2,'MarkerSize',11);
2256 %
2257 % This is a rewrite of the m-file errorbarxy of James Rooney, to add
2258 % customizable line properties.
2259
2260 % ------------------ INFO ------------------
2261 % Authors: Jean-Yves Tinevez
2262 % Work address: Max-Plank Insitute for Cell Biology and Genetics,
2263 % Dresden, Germany.
2264 % Email: tinevez AT mpi-cbg DOT de
2265 % November 2007 - June 2008;
2266 % Permission is given to distribute and modify this file as long as this
2267 % notice remains in it. Permission is also given to write to the author
2268 % for any suggestion, comment, modification or usage.
2269 % ------------------ BEGIN CODE ------------------
2270
2271 function out = errorbarxy(ax, x,y,varargin)
2272
2273
2274 nargs = length(varargin);
2275
2276 for i = 1 : nargs
2277
2278 if ~( isnumeric(varargin{i}) )
2279 break
2280 end
2281 errbaropt{i} = varargin{i};
2282
2283 end
2284
2285
2286 if i+3 < nargin
2287 displayopt = varargin(i:end);
2288 if isstruct(displayopt{1})
2289 options = displayopt{1};
2290 else
2291 options = varargin2struct(displayopt);
2292 end
2293 erroroptions = options;
2294 else
2295 displayopt = [];
2296 end
2297
2298 options.Color = 'k';
2299 erroroptions.LineStyle = '-';
2300 erroroptions.Marker = 'none';
2301
2302
2303 xw = (max(x)-min(x))/100;
2304 yw = (max(y)-min(y))/100;
2305
2306 n = length(varargin) - length(displayopt);
2307
2308 if n == 2
2309 % only 2 cells, so this is the same for lower and upper bar
2310 ux = errbaropt{1};
2311 lx = ux;
2312 uy = errbaropt{2};
2313 ly = uy;
2314
2315 elseif n == 4
2316 % 4 cells, the user specified both upper and lower limit
2317 ux = errbaropt{1};
2318 lx = errbaropt{3};
2319 uy = errbaropt{2};
2320 ly = errbaropt{4};
2321
2322 else
2323 errid = 'MATLAB:errorbarxy:BadArgumentNumber';
2324 errmsg = ['Must have 4 or 6 numeric arguments, got ' ,num2str(n+2),'.'];
2325 error(errid,errmsg);
2326
2327 end
2328
2329
2330 %%
2331
2332 holdstate = ishold(gca);
2333 X = [];
2334 Y = [];
2335 for t = 1:length(x)
2336
2337 % x errorbars
2338 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) ];
2339 Y = [ Y nan y(t) y(t) nan y(t)-yw y(t)+yw nan y(t)-yw y(t)+yw ];
2340
2341 % y errorbars
2342 X = [ X nan x(t) x(t) nan x(t)-xw x(t)+xw nan x(t)-xw x(t)+xw ];
2343 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) ];
2344
2345 end
2346
2347 hold on
2348 axes(ax);
2349 he = line(X,Y,erroroptions);
2350 hp = plot(ax, x,y,options);
2351 out = [hp he];
2352
2353 % Return to initial hold state if needed
2354 if ~holdstate
2355 hold off
2356 end
2357
2358 function out = varargin2struct(in)
2359 % I hould write help
2360
2361 if ~iscell(in)
2362 errid = 'MATLAB:struct2varargin:BadInputType';
2363 errmsg = ['Input argument must be a cell, got a ' ,class(in),'.'];
2364 error(errid,errmsg);
2365 end
2366
2367 n = length(in);
2368
2369 if mod(n,2) ~= 0
2370 errid = 'MATLAB:struct2varargin:BadInputType';
2371 errmsg = ['Input argument must have an even number of elements, got ' ,num2str(n),'.'];
2372 error(errid,errmsg);
2373 end
2374
2375 out = struct;
2376
2377 for jj = 1 : n/2
2378 name = in{2*jj-1};
2379 value = in{2*jj};
2380 out.(name) = value;
2381 end
2382
2383 end
2384
2385 end
2386
2387 % Get a suitable ymin and ymax (in logscale) for the given
2388 % data.
2389 function [ticks,ymin,ymax] = getRealYDataTicks(y, ymin, ymax, complexPlotType, scale)
2390
2391 ticks = [];
2392 switch complexPlotType
2393 case 'realimag'
2394 if strcmpi(scale', 'log')
2395
2396 % do nothing because it doesn't make sense since we will have
2397 % negative values on a log scale
2398
2399 end
2400 case {'absdeg', 'absrad'}
2401
2402 if strcmpi(scale, 'log')
2403 % This is the main case we want to cover.
2404 ay = abs(y);
2405 newymin = min(ymin, floor(log10(min(ay(ay>0)))));
2406 newymax = max(ymax, ceil(log10(max(ay(ay>0)))));
2407
2408 if ~isempty(newymin) && ~isempty(newymax)
2409 ymin = newymin;
2410 ymax = newymax;
2411
2412 if ymin == ymax
2413 ymin = floor(log10(min(ay)/10));
2414 ymax = ceil(log10(max(ay)*10));
2415 end
2416
2417 else
2418
2419 if ymin == inf
2420 ymin = -1;
2421 end
2422
2423 if ymax == -inf
2424 ymax = 1;
2425 end
2426
2427 end
2428 nticks = ymax - ymin +1;
2429 % can we reduce this if they don't all fit?
2430
2431 ticks = logspace(ymin, ymax, nticks);
2432 end
2433
2434 otherwise
2435 error('### Unknown plot type for complex data');
2436 end
2437
2438 end
2439
2440 % Get a suitable ymin and ymax (in linscale) for the given
2441 % data.
2442 function ticks = getImagYDataTicks(y, ymin, ymax, complexPlotType, scale)
2443
2444
2445 ticks = [];
2446 switch complexPlotType
2447 case 'realimag'
2448 if strcmpi(scale', 'log')
2449
2450 % do nothing because it doesn't make sense since we will have
2451 % negative values on a log scale
2452
2453 end
2454 case 'absdeg'
2455
2456 if strcmpi(scale', 'log')
2457 % do nothing because it doesn't make sense since we will have
2458 % negative values on a log scale
2459 end
2460
2461 case 'absrad'
2462
2463 otherwise
2464 error('### Unknown plot type for complex data');
2465 end
2466
2467
2468 end
2469
2470
2471 %-------------------
2472 % Process errorbars
2473 function [fcn, xu, xl, yu, yl] = process_errors(jj, dsize, ptype, XerrU, XerrL, YerrU, YerrL, a, auto)
2474
2475 if numel(XerrL) == 1
2476 xl = XerrL{1};
2477 else
2478 xl = XerrL{jj};
2479 end
2480 if numel(XerrU) == 1
2481 xu = XerrU{1};
2482 else
2483 xu = XerrU{jj};
2484 end
2485 if numel(YerrL) == 1
2486 yl = YerrL{1};
2487 else
2488 yl = YerrL{jj};
2489 end
2490 if numel(YerrU) == 1
2491 yu = YerrU{1};
2492 else
2493 yu = YerrU{jj};
2494 end
2495
2496 % Check if we have AOs
2497 if isa(xl, 'ao'), xl = xl.data.getY; end
2498 if isa(xu, 'ao'), xu = xu.data.getY; end
2499 if isa(yl, 'ao'), yl = yl.data.getY; end
2500 if isa(yu, 'ao'), yu = yu.data.getY; end
2501
2502 if isempty(xl) && ~isempty(xu)
2503 xl = xu;
2504 end
2505 if isempty(xu) && ~isempty(xl)
2506 xu = xl;
2507 end
2508 if isempty(yl) && ~isempty(yu)
2509 yl = yu;
2510 end
2511 if isempty(yu) && ~isempty(yl)
2512 yu = yl;
2513 end
2514
2515
2516
2517 % If the AO has errors, we use them
2518 if ~isempty(a.dy) && auto
2519 yl = a.dy;
2520 yu = a.dy;
2521 yu(yu==inf) = 0;
2522 yl(yl==inf) = 0;
2523 end
2524
2525 if isempty(xl) && isempty(xu) && isempty(yu) && isempty(yl)
2526 fcn = ptype;
2527 elseif isempty(xl) && isempty(xu)
2528 fcn = 'errorbar';
2529 else
2530 fcn = 'errorbarxy';
2531 end
2532
2533 if isempty(xl), xl = zeros(dsize); end
2534 if isempty(yl), yl = zeros(dsize); end
2535 if isempty(xu), xu = zeros(dsize); end
2536 if isempty(yu), yu = zeros(dsize); end
2537 if numel(xl) == 1, xl = xl.*ones(dsize); end
2538 if numel(xu) == 1, xu = xu.*ones(dsize); end
2539 if numel(yu) == 1, yu = yu.*ones(dsize); end
2540 if numel(yl) == 1, yl = yl.*ones(dsize); end
2541 end
2542
2543 function applyPlotSettings(axesH, lineH)
2544
2545 prefs = getappdata(0, 'LTPDApreferences');
2546 jPlotPrefs = prefs.getPlotPrefs();
2547
2548 if jPlotPrefs.getPlotApplyPlotSettings.equals(mpipeline.ltpdapreferences.EnumPlotSetting.IPLOT_ONLY)
2549
2550 % Set all axes properteis
2551 for ii =1:numel(axesH)
2552 set(axesH(ii), 'FontSize', double(jPlotPrefs.getPlotDefaultAxesFontSize));
2553 set(axesH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultAxesLineWidth));
2554 set(axesH(ii), 'GridLineStyle', char(jPlotPrefs.getPlotDefaultAxesGridLineStyle));
2555 set(axesH(ii), 'MinorGridLineStyle', char(jPlotPrefs.getPlotDefaultAxesMinorGridLineStyle));
2556 switch char(jPlotPrefs.getPlotDefaultAxesFontWeight)
2557 case 'Plain'
2558 set(axesH(ii), 'FontWeight', 'normal');
2559 case 'Bold'
2560 set(axesH(ii), 'FontWeight', 'bold');
2561 case 'Italic'
2562 set(axesH(ii), 'FontWeight', 'light');
2563 case 'Bold Italic'
2564 set(axesH(ii), 'FontWeight', 'demi');
2565 otherwise
2566 error('### Unknown value (%s) for the default axes property ''FontWeight''', char(jPlotPrefs.getPlotDefaultAxesFontWeight));
2567 end
2568 end
2569
2570 % Set all line properties
2571 for ii = 1:numel(lineH)
2572 set(lineH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultLineLineWidth));
2573 set(lineH(ii), 'MarkerSize', double(jPlotPrefs.getPlotDefaultLineMarkerSize));
2574 end
2575 end
2576 end