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.137 2011/04/10 06:45:01 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.137 2011/04/10 06:45:01 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 plout = pl;
1776 end
1777
1778 function out = buildplist(set)
1779
1780 % Get the LTPDA color set for lines
1781 colors = getappdata(0,'ltpda_default_plot_colors');
1782
1783 out = plist();
1784
1785 % Figure
1786 p = param({'Figure',['The handle of the figure to plot in to. This will be ignored if the AOs to plot are inconsistent,<br>'...
1787 'containing different class of data (such as tsdata and fsdata), or if the ''arrangement''<br>',...
1788 'parameter is passed as ''single''.']}, paramValue.EMPTY_DOUBLE);
1789 out.append(p);
1790
1791 % Colors
1792 p = param({'Colors', 'A list of colors which will be cycled through for each line in a plot.'}, colors);
1793 out.append(p);
1794
1795 % Arrangement
1796 p = param({'Arrangement',['Select the plot layout:<ul>',...
1797 '<li>''single'' - plot all AOs on individual figures</li>',...
1798 '<li>''stacked'' - plot all AOs on the same axes</li>',...
1799 '<li>''subplots'' - plot all AOs on subplots</li>'...
1800 '</ul>']}, {1, {'stacked', 'single', 'subplots'}, paramValue.SINGLE});
1801 out.append(p);
1802
1803 % Function
1804 p = param({'Function',['Specify the plot function:<ul>',...
1805 '<li>''plot''</li>', ...
1806 '<li>''stairs''</li>',...
1807 '<li>''stem''</li>',...
1808 '</ul>'...
1809 '[*** doesn''t work for xyzdata AOs]']}, {1, {'plot', 'stairs', 'stem'}, paramValue.SINGLE});
1810 out.append(p);
1811
1812 % LineColors
1813 p = param({'LineColors', ['A cell-array of color definitions, one for each trace.<br>'...
1814 'Give an empty string to use the default color.']}, ...
1815 {1, {''}, paramValue.OPTIONAL});
1816 out.append(p);
1817
1818 % LineColors
1819 p = param({'LineStyles', ['A cell-array of line styles, one for each trace.<br>'...
1820 'Give an empty string to use the default style.']}, ...
1821 {1, {''}, paramValue.OPTIONAL});
1822 out.append(p);
1823
1824 % Markers
1825 p = param({'Markers', ['A cell-array of markers, one for each trace.']}, ...
1826 {1, {''}, paramValue.OPTIONAL});
1827 out.append(p);
1828
1829 % LineWidths
1830 p = param({'LineWidths', ['A cell-array of line widths, one for each trace.<br>'...
1831 'Give an empty string to use the default line width.']}, ...
1832 {1, {''}, paramValue.OPTIONAL});
1833 out.append(p);
1834
1835 % Legends
1836 p = param({'Legends', ['Give a cell-array of strings to be used for<br>'...
1837 'the plot legends. If a cell contains an empty<br>'...
1838 'string, the default legend string is built.<br>'...
1839 'If a single string ''off'' is given instead of a<br>'...
1840 'cell-array, then the legends are all switched off.']}, ...
1841 {1, {''}, paramValue.OPTIONAL});
1842 out.append(p);
1843
1844 % LegendLocation
1845 p = param({'LegendLocation','Choose the legend location.'}, ...
1846 {5, {'North', 'South', 'East', 'West', ...
1847 'NorthEast', 'NorthWest', 'SouthEast', 'SouthWest', ...
1848 'NorthOutside', 'SouthOutside', 'EastOutside', 'WestOutside', ...
1849 'NorthEastOutside', 'NorthWestOutside', 'SouthEastOutside', ...
1850 'SouthWestOutside', 'Best', 'BestOutside'}, paramValue.SINGLE});
1851 out.append(p);
1852
1853 % LegendFontSize
1854 p = param({'LegendFontSize','Choose the legend font size.'}, ...
1855 {1, {LTPDAprefs.legendFontSize}, paramValue.SINGLE});
1856 out.append(p);
1857
1858 % XerrL
1859 p = param({'XerrL','Lower bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1860 out.append(p);
1861
1862 % XerrU
1863 p = param({'XerrU','Upper bound error values for the X data points.'}, paramValue.EMPTY_DOUBLE);
1864 out.append(p);
1865
1866 % YerrL
1867 p = param({'YerrL','Lower bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1868 out.append(p);
1869
1870 % YerrU
1871 p = param({'YerrU','Upper bound error values for the Y data points.'}, paramValue.EMPTY_DOUBLE);
1872 out.append(p);
1873
1874 % XScales
1875 p = param({'XScales', ['A cell-array specifying the scale to be used on each x-axis.<br>'...
1876 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1877 out.append(p);
1878
1879 % YScales
1880 p = param({'YScales', ['A cell-array specifying the scale to be used on each y-axis.<br>'...
1881 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
1882 out.append(p);
1883
1884 % XRanges
1885 p = param({'XRanges', ['A cell-array specifying the ranges to be displayed on each x-axis.<br>'...
1886 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1887 out.append(p);
1888
1889 % YRanges
1890 p = param({'YRanges', ['A cell-array specifying the ranges to be displayed on each y-axis.<br>'...
1891 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
1892 out.append(p);
1893
1894 % LatexLabels
1895 p = param({'LatexLabels','Use latex interpreter for axis labels.'}, paramValue.TRUE_FALSE);
1896 p.val.setValIndex(2);
1897 out.append(p);
1898
1899 % YMaths
1900 p = param({'YMaths',['Specify math operations to perform on the data vector ''y''. [DEPRECATED]<br>',...
1901 'For example, <tt>plist(''Ymaths'', ''sqrt(y)'')</tt>.']}, paramValue.EMPTY_STRING);
1902 out.append(p);
1903
1904
1905 % No auto-errors
1906 p = param({'AUTOERRORS',['If the AO contains errors, they will be plotted. You can avoid plotting the <br>',...
1907 'errors by setting this to false.']}, paramValue.FALSE_TRUE);
1908 out.append(p);
1909
1910 switch lower(set)
1911 case 'frequency-series plot'
1912 % ComplexPlotType
1913 p = param({'complexPlotType',['Specify how to plot complex data. Choose from:<ul>',...
1914 '<li>''realimag''</li>',...
1915 '<li>''absdeg''</li>',...
1916 '<li>''absrad''</li>'...
1917 '</ul>']}, {1, {'absdeg', 'realimag', 'absrad'}, paramValue.SINGLE});
1918 out.append(p);
1919
1920 % Xlabel
1921 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1922 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1923 out.append(p);
1924 % ylabels
1925 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1926 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE(''));
1927 out.append(p);
1928
1929 % XMaths
1930 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1931 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1932 out.append(p);
1933
1934 case 'time-series plot'
1935
1936 % Xlabel
1937 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1938 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1939 out.append(p);
1940
1941 % Ylabels
1942 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1943 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
1944 out.append(p);
1945
1946 % Xunits
1947 p = param({'Xunits', ['Specify the units of time on the x-axis as<ul>'...
1948 '<li>''us'' - microseconds<li>' ...
1949 '<li>''ms'' - milliseconds<li>' ...
1950 '<li>''s'' - seconds<li>' ...
1951 '<li>''m'' - minutes<li>' ...
1952 '<li>''h'' - hours<li>' ...
1953 '<li>''D'' - days<li>' ...
1954 '<li>''M'' - months<li>' ...
1955 '<li>''HH:MM:SS'' - using a date/time format</li>' ...
1956 '</ul>']}, {3, {'us', 'ms', 's', 'm', 'h', 'D', 'M', 'HH:MM:SS', 'yyyy-mm-dd HH:MM:SS'}, paramValue.OPTIONAL});
1957 out.append(p);
1958
1959 case 'x-y data plot'
1960 % Xlabel
1961 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1962 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('X-data'));
1963 out.append(p);
1964
1965 % Ylabels
1966 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1967 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Y-data'));
1968 out.append(p);
1969
1970 % XMaths
1971 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1972 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1973 out.append(p);
1974
1975 case '3d plot'
1976
1977 out.pset('arrangement', 'single');
1978
1979 % Xlabel
1980 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
1981 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Time'));
1982 out.append(p);
1983
1984 % Ylabels
1985 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
1986 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Frequency'));
1987 out.append(p);
1988
1989 % Zlabels
1990 p = param({'ZLabels',['Specify the labels to be used on the z-axes. The units are added from<br>',...
1991 'the data object ''zunits'' property.']}, paramValue.STRING_VALUE('Amplitude'));
1992 out.append(p);
1993
1994 % XMaths
1995 p = param({'XMaths',['Specify math operations to perform on the data vector ''x''. [DEPRECATED]<br>',...
1996 'For example, <tt>plist(''Xmaths'', ''abs(x)'')</tt>.']}, paramValue.EMPTY_STRING);
1997 out.append(p);
1998
1999 % ZMaths
2000 p = param({'ZMaths',['Specify math operations to perform on the data vector ''z''. [DEPRECATED]<br>',...
2001 'For example, <tt>plist(''Zmaths'', ''abs(z)'')</tt>.']}, paramValue.EMPTY_STRING);
2002 out.append(p);
2003
2004 % ZScales
2005 p = param({'ZScales', ['A cell-array specifying the scale to be used on each z-axis.<br>'...
2006 'For example, {''lin'', ''log''}']}, {1, {''}, paramValue.OPTIONAL});
2007 out.append(p);
2008
2009 % ZRanges
2010 p = param({'ZRanges', ['A cell-array specifying the ranges to be displayed on each z-axis.<br>'...
2011 'For example, {[0 1], [-4 4]}.']}, {1, {''}, paramValue.OPTIONAL});
2012 out.append(p);
2013
2014 % Invert y-axis
2015 p = param({'InvertY', ['Invert the y-axis or not.']}, paramValue.TRUE_FALSE);
2016 out.append(p);
2017
2018 out.remove('linestyles');
2019 out.remove('linewidths');
2020 out.remove('linecolors');
2021 out.remove('markers');
2022
2023 case 'y data plot'
2024 % Xlabel
2025 p = param({'XLabels',['Specify the labels to be used on the x-axes. The units are added from<br>',...
2026 'the data object ''xunits'' property.']}, paramValue.STRING_VALUE('Sample'));
2027 out.append(p);
2028
2029 % Ylabels
2030 p = param({'YLabels',['Specify the labels to be used on the y-axes. The units are added from<br>',...
2031 'the data object ''yunits'' property.']}, paramValue.STRING_VALUE('Value'));
2032 out.append(p);
2033 otherwise
2034 error('### Unknown set [%s]', set);
2035 end
2036 end
2037
2038
2039 function name = makeLegendStr(a)
2040
2041 name = utils.plottools.label(a.name);
2042 desc = utils.plottools.label(a.description);
2043
2044 if isempty(name)
2045 name = '?';
2046 end
2047
2048 if ~isempty(desc) && LTPDAprefs.includeDescription
2049 name = [name ': ' desc];
2050 end
2051
2052
2053 end
2054
2055 % Perform some substitutions on the labels
2056 function ss = fixlabel(ss)
2057
2058 MAX_LENGTH = 50;
2059 wasCell = true;
2060 if ~iscell(ss)
2061 ss = {ss};
2062 wasCell = false;
2063 end
2064
2065 for kk = 1:numel(ss)
2066 s = ss{kk};
2067 if ~isempty(s)
2068 % Replace all ^(...) with ^{...}
2069 jj = 1;
2070 while jj < numel(s)
2071 if strcmp(s(jj:jj+1), '^(')
2072 % find next )
2073 for k = 1:numel(s)-jj+1
2074 if s(jj+k) == ')'
2075 s(jj+1) = '{';
2076 s(jj+k) = '}';
2077 break;
2078 end
2079 end
2080 end
2081 jj = jj + 1;
2082 end
2083 % Replace all .^ with ^
2084 s = strrep(s, '.^', '^');
2085
2086 % reduce size
2087 if length(s) > MAX_LENGTH
2088 s = s(1:MAX_LENGTH-3);
2089 if s(end) == '\'
2090 s = s(1:end-1)
2091 end
2092 s = [ s '...' ];
2093 end
2094
2095 end
2096 ss(kk) = {s};
2097 end
2098
2099 if ~wasCell
2100 ss = ss{1};
2101 end
2102
2103 end
2104
2105 %-----------------------------------------------
2106 % Change X data for time-series according to the specified xunits
2107 function [x, xunit, dateTicSpec] = convertXunits(x, t0, xunit, xunitIn)
2108
2109 dateTicSpec = false;
2110
2111 xunit = strtrim(xunit);
2112 xunitIn = strtrim(xunitIn);
2113 if ~strcmpi(strtrim(xunitIn), '[s]')
2114 warning('### I can only convert from [s] to %s - ignoring requested Xunit', xunit);
2115 xunit = xunitIn;
2116 else
2117 switch strtrim(xunit)
2118 case {'[us]', 'us'}
2119 x = x .* 1e6;
2120 case {'[ms]', 'ms'}
2121 x = x .* 1e3;
2122 case {'[s]', 's'}
2123 case {'[m]', 'm'}
2124 x = x ./ 60;
2125 case {'[h]', 'h'}
2126 x = x ./ 3600;
2127 case {'[D]', 'D'}
2128 x = x ./ 86400;
2129 otherwise
2130 % then we have a datetic spec
2131 dateTicSpec = true;
2132 % first convert x data to serial date
2133 st = format(t0, 'yyyy-mm-dd hh:mm:ss');
2134 st = regexp(st, ' ', 'split');
2135 st = [st{1} ' ' st{2}];
2136 t0 = datenum(st); % get t0 as a serial date
2137 x = t0 + x./86400; % convert x to days
2138 end
2139 end
2140 if xunit(1) ~= '['
2141 xunit = ['[' xunit];
2142 end
2143 if xunit(end) ~= ']'
2144 xunit = [xunit ']'];
2145 end
2146 % 'us' - microseconds
2147 % 'ms' - milliseconds
2148 % 's' - seconds [default]
2149 % 'm' - minutes
2150 % 'h' - hours
2151 % 'D' - days
2152 % 'M' - months
2153 % 'HH:MM:SS' - using a date/time format
2154
2155 end
2156
2157 %----------------------------------------
2158 % Prepare an axis label
2159 function lstr = prepareAxisLabel(units, math, lstr, axis, UseLatex)
2160 if isa(units, 'unit')
2161
2162 if ismac && UseLatex
2163 units = units.tolabel;
2164 else
2165 units = {fixlabel(char(units))};
2166 end
2167 else
2168 units = {units};
2169 end
2170 if ~isempty(math)
2171 if ~isempty(lstr)
2172 lstr = strrep(math, axis, lstr);
2173 end
2174 lstr = [fixlabel(lstr) ' ' units{1} ];
2175 else
2176 lstr = [fixlabel(lstr) ' ' units{1}];
2177 end
2178 end
2179
2180 % Parse cell-array of options
2181 function opt = parseOptions(varargin) %jj, opts, dopt
2182
2183 jj = varargin{1};
2184 opts = varargin{2};
2185 dopt = varargin{3};
2186 opt = dopt;
2187
2188 if ~iscell(opts)
2189 opts = {opts};
2190 end
2191 Nopts = numel(opts);
2192
2193 % First look for the 'all' keyword
2194 if Nopts == 2 && strcmpi(opts{1}, 'all')
2195 opt = opts{2};
2196 else
2197 if jj <= Nopts && ~isempty(opts{jj})
2198 opt = opts{jj};
2199 end
2200 end
2201
2202 end
2203
2204
2205
2206 % ERRORBARXY Customizable error bar plot in X and Y direction
2207 %
2208 % This function allows the user to plot the graph of x against y, along with
2209 % both x and y errorbars.
2210 %
2211 % With 4 numeric arguments (x,y,dx,dy), error bar are assumed to be of
2212 % same magnitude in both direction.
2213 %
2214 % One can specify lower and upper error bar with 6 numeric arguments
2215 % (x,y,dx_high,dy_high,dx_low,dy_low).
2216 %
2217 % x,y,dx,dy,... must be vectors of the same length
2218 %
2219 % [hp he] = errorbarxy(...) returns respectively the handle for the line
2220 % plot object and the line error bar object.
2221 %
2222 % It is pos1sible to customize the line properties of the error bars by
2223 % adding pair of 'field/value' fields (such as 'LineWidth',2) that can be
2224 % understood by line. See LineProperties for more information.
2225 %
2226 % --------
2227 % EXAMPLES
2228 % --------
2229 % X = 10 * rand(7,1);
2230 % Y = 10 * rand(7,1);
2231 % dx = rand(7,1);
2232 % dy = rand(7,1);
2233 % errorbarxy(X,Y,dx,dy,'Color','k','LineStyle','none','Marker','o',...
2234 % 'MarkerFaceColor','w','LineWidth',1,'MarkerSize',11);
2235 %
2236 % X = 10 * rand(7,1);
2237 % Y = 10 * rand(7,1);
2238 % dx = rand(7,1);
2239 % dy = rand(7,1);
2240 % dx2 = rand(7,1);
2241 % dy2 = rand(7,1);
2242 % errorbarxy(X,Y,dx,dy,dx2,dy2,'Color','B','LineStyle','--','Marker','s',...
2243 % 'MarkerFaceColor','w','LineWidth',2,'MarkerSize',11);
2244 %
2245 % This is a rewrite of the m-file errorbarxy of James Rooney, to add
2246 % customizable line properties.
2247
2248 % ------------------ INFO ------------------
2249 % Authors: Jean-Yves Tinevez
2250 % Work address: Max-Plank Insitute for Cell Biology and Genetics,
2251 % Dresden, Germany.
2252 % Email: tinevez AT mpi-cbg DOT de
2253 % November 2007 - June 2008;
2254 % Permission is given to distribute and modify this file as long as this
2255 % notice remains in it. Permission is also given to write to the author
2256 % for any suggestion, comment, modification or usage.
2257 % ------------------ BEGIN CODE ------------------
2258
2259 function out = errorbarxy(ax, x,y,varargin)
2260
2261
2262 nargs = length(varargin);
2263
2264 for i = 1 : nargs
2265
2266 if ~( isnumeric(varargin{i}) )
2267 break
2268 end
2269 errbaropt{i} = varargin{i};
2270
2271 end
2272
2273
2274 if i+3 < nargin
2275 displayopt = varargin(i:end);
2276 if isstruct(displayopt{1})
2277 options = displayopt{1};
2278 else
2279 options = varargin2struct(displayopt);
2280 end
2281 erroroptions = options;
2282 else
2283 displayopt = [];
2284 end
2285
2286 options.Color = 'k';
2287 erroroptions.LineStyle = '-';
2288 erroroptions.Marker = 'none';
2289
2290
2291 xw = (max(x)-min(x))/100;
2292 yw = (max(y)-min(y))/100;
2293
2294 n = length(varargin) - length(displayopt);
2295
2296 if n == 2
2297 % only 2 cells, so this is the same for lower and upper bar
2298 ux = errbaropt{1};
2299 lx = ux;
2300 uy = errbaropt{2};
2301 ly = uy;
2302
2303 elseif n == 4
2304 % 4 cells, the user specified both upper and lower limit
2305 ux = errbaropt{1};
2306 lx = errbaropt{3};
2307 uy = errbaropt{2};
2308 ly = errbaropt{4};
2309
2310 else
2311 errid = 'MATLAB:errorbarxy:BadArgumentNumber';
2312 errmsg = ['Must have 4 or 6 numeric arguments, got ' ,num2str(n+2),'.'];
2313 error(errid,errmsg);
2314
2315 end
2316
2317
2318 %%
2319
2320 holdstate = ishold(gca);
2321 X = [];
2322 Y = [];
2323 for t = 1:length(x)
2324
2325 % x errorbars
2326 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) ];
2327 Y = [ Y nan y(t) y(t) nan y(t)-yw y(t)+yw nan y(t)-yw y(t)+yw ];
2328
2329 % y errorbars
2330 X = [ X nan x(t) x(t) nan x(t)-xw x(t)+xw nan x(t)-xw x(t)+xw ];
2331 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) ];
2332
2333 end
2334
2335 hold on
2336 axes(ax);
2337 he = line(X,Y,erroroptions);
2338 hp = plot(ax, x,y,options);
2339 out = [hp he];
2340
2341 % Return to initial hold state if needed
2342 if ~holdstate
2343 hold off
2344 end
2345
2346 function out = varargin2struct(in)
2347 % I hould write help
2348
2349 if ~iscell(in)
2350 errid = 'MATLAB:struct2varargin:BadInputType';
2351 errmsg = ['Input argument must be a cell, got a ' ,class(in),'.'];
2352 error(errid,errmsg);
2353 end
2354
2355 n = length(in);
2356
2357 if mod(n,2) ~= 0
2358 errid = 'MATLAB:struct2varargin:BadInputType';
2359 errmsg = ['Input argument must have an even number of elements, got ' ,num2str(n),'.'];
2360 error(errid,errmsg);
2361 end
2362
2363 out = struct;
2364
2365 for jj = 1 : n/2
2366 name = in{2*jj-1};
2367 value = in{2*jj};
2368 out.(name) = value;
2369 end
2370
2371 end
2372
2373 end
2374
2375 % Get a suitable ymin and ymax (in logscale) for the given
2376 % data.
2377 function [ticks,ymin,ymax] = getRealYDataTicks(y, ymin, ymax, complexPlotType, scale)
2378
2379 ticks = [];
2380 switch complexPlotType
2381 case 'realimag'
2382 if strcmpi(scale', 'log')
2383
2384 % do nothing because it doesn't make sense since we will have
2385 % negative values on a log scale
2386
2387 end
2388 case {'absdeg', 'absrad'}
2389
2390 if strcmpi(scale, 'log')
2391 % This is the main case we want to cover.
2392 ay = abs(y);
2393 newymin = min(ymin, floor(log10(min(ay(ay>0)))));
2394 newymax = max(ymax, ceil(log10(max(ay(ay>0)))));
2395
2396 if ~isempty(newymin) && ~isempty(newymax)
2397 ymin = newymin;
2398 ymax = newymax;
2399
2400 if ymin == ymax
2401 ymin = floor(log10(min(ay)/10));
2402 ymax = ceil(log10(max(ay)*10));
2403 end
2404
2405 else
2406
2407 if ymin == inf
2408 ymin = -1;
2409 end
2410
2411 if ymax == -inf
2412 ymax = 1;
2413 end
2414
2415 end
2416 nticks = ymax - ymin +1;
2417 % can we reduce this if they don't all fit?
2418
2419 ticks = logspace(ymin, ymax, nticks);
2420 end
2421
2422 otherwise
2423 error('### Unknown plot type for complex data');
2424 end
2425
2426 end
2427
2428 % Get a suitable ymin and ymax (in linscale) for the given
2429 % data.
2430 function ticks = getImagYDataTicks(y, ymin, ymax, complexPlotType, scale)
2431
2432
2433 ticks = [];
2434 switch complexPlotType
2435 case 'realimag'
2436 if strcmpi(scale', 'log')
2437
2438 % do nothing because it doesn't make sense since we will have
2439 % negative values on a log scale
2440
2441 end
2442 case 'absdeg'
2443
2444 if strcmpi(scale', 'log')
2445 % do nothing because it doesn't make sense since we will have
2446 % negative values on a log scale
2447 end
2448
2449 case 'absrad'
2450
2451 otherwise
2452 error('### Unknown plot type for complex data');
2453 end
2454
2455
2456 end
2457
2458
2459 %-------------------
2460 % Process errorbars
2461 function [fcn, xu, xl, yu, yl] = process_errors(jj, dsize, ptype, XerrU, XerrL, YerrU, YerrL, a, auto)
2462
2463 if numel(XerrL) == 1
2464 xl = XerrL{1};
2465 else
2466 xl = XerrL{jj};
2467 end
2468 if numel(XerrU) == 1
2469 xu = XerrU{1};
2470 else
2471 xu = XerrU{jj};
2472 end
2473 if numel(YerrL) == 1
2474 yl = YerrL{1};
2475 else
2476 yl = YerrL{jj};
2477 end
2478 if numel(YerrU) == 1
2479 yu = YerrU{1};
2480 else
2481 yu = YerrU{jj};
2482 end
2483
2484 % Check if we have AOs
2485 if isa(xl, 'ao'), xl = xl.data.getY; end
2486 if isa(xu, 'ao'), xu = xu.data.getY; end
2487 if isa(yl, 'ao'), yl = yl.data.getY; end
2488 if isa(yu, 'ao'), yu = yu.data.getY; end
2489
2490 if isempty(xl) && ~isempty(xu)
2491 xl = xu;
2492 end
2493 if isempty(xu) && ~isempty(xl)
2494 xu = xl;
2495 end
2496 if isempty(yl) && ~isempty(yu)
2497 yl = yu;
2498 end
2499 if isempty(yu) && ~isempty(yl)
2500 yu = yl;
2501 end
2502
2503
2504
2505 % If the AO has errors, we use them
2506 if ~isempty(a.dy) && auto
2507 yl = a.dy;
2508 yu = a.dy;
2509 yu(yu==inf) = 0;
2510 yl(yl==inf) = 0;
2511 end
2512
2513 if isempty(xl) && isempty(xu) && isempty(yu) && isempty(yl)
2514 fcn = ptype;
2515 elseif isempty(xl) && isempty(xu)
2516 fcn = 'errorbar';
2517 else
2518 fcn = 'errorbarxy';
2519 end
2520
2521 if isempty(xl), xl = zeros(dsize); end
2522 if isempty(yl), yl = zeros(dsize); end
2523 if isempty(xu), xu = zeros(dsize); end
2524 if isempty(yu), yu = zeros(dsize); end
2525 if numel(xl) == 1, xl = xl.*ones(dsize); end
2526 if numel(xu) == 1, xu = xu.*ones(dsize); end
2527 if numel(yu) == 1, yu = yu.*ones(dsize); end
2528 if numel(yl) == 1, yl = yl.*ones(dsize); end
2529 end
2530
2531 function applyPlotSettings(axesH, lineH)
2532
2533 prefs = getappdata(0, 'LTPDApreferences');
2534 jPlotPrefs = prefs.getPlotPrefs();
2535
2536 if jPlotPrefs.getPlotApplyPlotSettings.equals(mpipeline.ltpdapreferences.EnumPlotSetting.IPLOT_ONLY)
2537
2538 % Set all axes properteis
2539 for ii =1:numel(axesH)
2540 set(axesH(ii), 'FontSize', double(jPlotPrefs.getPlotDefaultAxesFontSize));
2541 set(axesH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultAxesLineWidth));
2542 set(axesH(ii), 'GridLineStyle', char(jPlotPrefs.getPlotDefaultAxesGridLineStyle));
2543 set(axesH(ii), 'MinorGridLineStyle', char(jPlotPrefs.getPlotDefaultAxesMinorGridLineStyle));
2544 switch char(jPlotPrefs.getPlotDefaultAxesFontWeight)
2545 case 'Plain'
2546 set(axesH(ii), 'FontWeight', 'normal');
2547 case 'Bold'
2548 set(axesH(ii), 'FontWeight', 'bold');
2549 case 'Italic'
2550 set(axesH(ii), 'FontWeight', 'light');
2551 case 'Bold Italic'
2552 set(axesH(ii), 'FontWeight', 'demi');
2553 otherwise
2554 error('### Unknown value (%s) for the default axes property ''FontWeight''', char(jPlotPrefs.getPlotDefaultAxesFontWeight));
2555 end
2556 end
2557
2558 % Set all line properties
2559 for ii = 1:numel(lineH)
2560 set(lineH(ii), 'LineWidth', double(jPlotPrefs.getPlotDefaultLineLineWidth));
2561 set(lineH(ii), 'MarkerSize', double(jPlotPrefs.getPlotDefaultLineMarkerSize));
2562 end
2563 end
2564 end