function varargout = miplot(varargin)
% MIPLOT provides an intelligent plotting tool for LTPDA.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: MIPLOT provides an intelligent plotting tool for LTPDA.
%
% CALL:        h = plot (a,pl)
%
% INPUTS:      pl   - a parameter list
%              a    - input analysis object
%
% OUTPUTS:     h - handles to plot objects
%
% Plot parameters: 
% 
%             'type' - one of the data class types
%                      'tsdata' [default], 'fsdata', 'cdata', 'xydata', 'xyzdata'.
%
%             'Arrangement' - select the plot layout:
%                           'single'   - plots all AOs on individual figures
%                           'stacked'  - plots all AOs on the same axes [default]
%                           'subplots' - plots all AOs on subplots
% 
% Line parameters:
% 
%        The following properties take cell array values. If the length of 
%        the cell array is shorter than the number of lines to plot, the 
%        remaining lines will be plotted with the default options.
% 
%             'Colors' - a cell array of color definitions which will be
%                        looped over for each line.
% 
%             'LineStyles' - a cell array of line styles. 
% 
%             'Legends' - specify a cell array of strings to be used for
%                         the plot legends. If a cell contains an empty
%                         string, the default legend string is built. 
%                         If a single string 'off' is given instead of a
%                         cell array, then the legends are all switched
%                         off.
% 
%             'XLabels' - Specify the labels to be used on the x-axis. The
%                         units are added from the data object 'xunits'
%                         property.
% 
%             'YLabels' - Specify the labels to be used on the y-axis. The
%                         units are added from the data object 'yunits'
%                         property. If the object contains complex data,
%                         you should specify two y-labels for that object.
% 
%             'XScales' - Specify the scales to be used on the x-axes.
% 
%             'YScales' - Specify the scales to the used on the y-axes. If
%                         an object contains complex data, you should 
%                         specify two y-labels for that object.
% 
%             'LineWidths' - an array of line widths. If the length of the
%                            array is shorter than the number of lines to
%                            plot, the remaining lines will be plotted with
%                            the default line width.
% 
% 
% 
% 
% 
% VERSION:     $Id: miplot.m,v 1.3 2008/02/07 19:51:53 hewitson Exp $
%
% The following call returns a parameter list object that contains the
% default parameter values:
%
% >> pl = miplot(ao, 'Params')
%
% HISTORY: 22-12-07 M Hewitson
%             Creation
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% TODO:
%    1) Add XRange, YRange, ZRange
%    2) Add/test math functions to all plots
% 
% 

%% Check if this is a call for parameters

VERSION = '$Id: miplot.m,v 1.3 2008/02/07 19:51:53 hewitson Exp $';
bs      = [];

if nargin == 2
  if isa(varargin{1}, 'ao') && ischar(varargin{2})
    in = char(varargin{2});
    if strcmp(in, 'Params')
      varargout{1} = getDefaultPL();
      return
    elseif strcmp(in, 'Version')
      varargout{1} = VERSION;
      return
    end
  end
end

%% Collect input ao's, plist's and ao variable names
in_names = {};
for ii = 1:nargin
  in_names{end+1} = inputname(ii);
end

[as, upl, invars] = collect_inputs(varargin, in_names);

%% Go through AOs and collect them into similar types

tsAOs  = [];
fsAOs  = [];
xyAOs  = [];
xyzAOs = [];
cAOs   = [];

for j=1:numel(as)
  switch class(as(j).data)
    case 'tsdata'
      tsAOs = [tsAOs as(j)];
    case 'fsdata'
      fsAOs = [fsAOs as(j)];
    case 'xydata'
      xyAOs = [xyAOs as(j)];
    case 'xyzdata'
      xyzAOs = [xyzAOs as(j)];
    case 'cdata'
      cAOs = [cAOs as(j)];
    otherwise
      warning('!!! Unknown data type %s', class(as(j).data));
  end
end

%% Now plot all the objects on separate figures

%----------- TSDATA

% get default plist
dpl = getDefaultPlist('tsdata');
% combine the plists
pl = combine(upl, dpl);
% Call x-y plot
[hfig, hax, hli] = xy_plot(tsAOs, pl);

%----------- XYDATA

% get default plist
dpl = getDefaultPlist('xydata');
% combine the plists
pl = combine(upl, dpl);
% Call x-y plot
[hfig, hax, hli] = xy_plot(xyAOs, pl);

%----------- XYZDATA

% get default plist
dpl = getDefaultPlist('xyzdata');
% combine the plists
pl = combine(upl, dpl);
% Call x-y-z plot
[hfig, hax, hli] = xyz_plot(xyzAOs, pl);

%----------- CDATA

% get default plist
dpl = getDefaultPlist('cdata');
% combine the plists
pl = combine(upl, dpl);
% Call x-y plot
[hfig, hax, hli] = y_plot(cAOs, pl);

%----------- FSDATA

% get default plist
dpl = getDefaultPlist('fsdata');
% combine the plists
pl = combine(upl, dpl);
% Call fsdata plot
[hfig, hax, hli] = fs_plot(fsAOs, pl);


%--------------------------------------------------------------------------
% Plot fsdata objects
%
function varargout = fs_plot(varargin)

aos = varargin{1};
pl  = varargin{2};

% Extract parameters
arrangement = find(pl, 'Arrangement');
colors      = find(pl, 'Colors');
linestyles  = find(pl, 'LineStyles');
linewidths  = find(pl, 'LineWidths');
legends     = find(pl, 'Legends');
ylabels     = find(pl, 'YLabels');
xlabels     = find(pl, 'XLabels');
yscales     = find(pl, 'YScales');
xscales     = find(pl, 'XScales');
yranges     = find(pl, 'YRanges');
xranges     = find(pl, 'XRanges');
xmaths      = find(pl, 'XMaths');
ymaths      = find(pl, 'YMaths');
complexPlotType = find(pl, 'complexPlotType');

% check whether we want legends or not
if iscell(legends)
  legendsOn = 1;
else
  if strcmpi(legends, 'off')
    legendsOn = 0;
  else
    legendsOn = 1;
    legends = [];
  end
end

if ~iscell(linestyles), linestyles = {linestyles}; end
if ~iscell(legends), legends = {legends}; end
if ~iscell(ylabels), ylabels = {ylabels}; end
if ~iscell(xlabels), xlabels = {xlabels}; end
if ~iscell(xmaths), xmaths = {xmaths}; end
if ~iscell(ymaths), ymaths = {ymaths}; end
if ~iscell(xscales), xscales = {xscales}; end
if ~iscell(yscales), yscales = {yscales}; end
if ~iscell(xranges), xranges = {xranges}; end
if ~iscell(yranges), yranges = {yranges}; end


% collect figure handles
tsfig = [];
tsax  = [];
tsli  = [];

% Legend holder
legendStr = [];

if ~isempty(aos)

  % Now loop over AOs
  Na = length(aos);
  
  % - first to check if any are complex
  haveComplex = 0;
  for j=1:Na
    a = aos(j);
    y = a.data.y;
    ymath = '';
    if j<=length(ymaths)
      if ~isempty(ymaths{j})
        eval(sprintf('y = %s;', ymaths{j}));
        ymath = ymaths{j};
      end
    end
    xmath = '';
    if j<=length(xmaths)
      if ~isempty(xmaths{j})
        eval(sprintf('x = %s;', xmaths{j}));
        xmath = xmaths{j};
      end
    end
    if ~isreal(y)
      haveComplex = 1;
    end    
  end
  
  % Loop over the AOs now  
  for j=1:Na
    
    % set real and imag subplot handles to empty
    tsax_r = [];
    tsax_i = [];
    
    % Get this AO
    a = aos(j);
    
    %------- Apply math functions
    x = a.data.x;
    y = a.data.y;
    
    ymath = '';
    if j<=length(ymaths)
      if ~isempty(ymaths{j})
        eval(sprintf('y = %s;', ymaths{j}));
        ymath = ymaths{j};
      end
    end
    xmath = '';
    if j<=length(xmaths)
      if ~isempty(xmaths{j})
        eval(sprintf('x = %s;', xmaths{j}));
        xmath = xmaths{j};
      end
    end
    
    % what figures do we need?
    switch arrangement
      case 'single'        
        
        tsfig = [tsfig figure];
        col = colors{1};
        % check if this data set is real or complex
        if ~isreal(y)
          % complex means we use two subplots
          tsax_r = subplot(2,1,1);
          tsax_i = subplot(2,1,2);
          tsax   = [tsax tsax_r tsax_i];
        else
          % real means we use a single subplot
          tsax_r = subplot(1, 1, 1);
          tsax = [tsax tsax_r];
        end
        
      case 'stacked'
        
        if j==1, tsfig = figure; end
        % if at least one of the input fsdata AOs is complex, we need to
        % allow for subplots
        if haveComplex
          tsax_r = subplot(2,1,1);
          tsax_i = subplot(2,1,2);
          tsax   = [tsax_r tsax_i];
        else
          tsax_r = subplot(1, 1, 1);
          tsax = tsax_r;
        end
        col = colors{mod(j-1,length(colors))+1};
        hold(tsax_r, 'on');
        if ishandle(tsax_i)
          hold(tsax_i, 'on');
        end      
      case 'subplots'
        
        if j == 1, tsfig = figure; end
        c = 1+(j-1)*2;
        sx = Na;
        sy = 2;
        % Now we have one or two subplots per input object.
        if ~isreal(y)
          tsax_r = subplot(sx, sy,c);
          tsax_i = subplot(sx, sy,c+1);
          tsax   = [tsax tsax_r tsax_i];
        else
          tsax_r = subplot(sx, sy, c:c+1);
          tsax   = [tsax tsax_r];
        end
        col = colors{1};
        
      otherwise
        error('### Unknown plot arrangement');
    end

    %------- Plot the data
    
    % plot real or complex data and setup default values for scale and
    % labels as we go.
    if isreal(y)
      tsli = [tsli plot(tsax_r, x, y)];
      ylabelr = 'amplitude';
      ylabeli = 'imag';
      yscaleR = 'log';
      yscaleI = 'lin';
      xscaleR = 'log';
      xscaleI = 'lin';
    else
      switch complexPlotType
        case 'realimag'
          tsli = [tsli plot(tsax_r, x, real(y))];
          tsli = [tsli plot(tsax_i, x, imag(y))];
          ylabelr = 'real';
          ylabeli = 'imag';
          yscaleR = 'lin';
          yscaleI = 'lin';
          xscaleR = 'lin';
          xscaleI = 'lin';
        case 'absdeg'
          tsli = [tsli plot(tsax_r, x, abs(y))];
          tsli = [tsli plot(tsax_i, x, phase(y))];
          ylabelr = 'amplitude';
          ylabeli = 'Phase [deg]';
          yscaleR = 'log';
          yscaleI = 'lin';
          xscaleR = 'log';
          xscaleI = 'log';
        case 'absrad'
          tsli = [tsli plot(tsax_r, x, abs(y))];
          tsli = [tsli plot(tsax_i, x, angle(y))];
          ylabelr = 'amplitude';
          ylabeli = 'phase [rad]';
          yscaleR = 'log';
          yscaleI = 'lin';
          xscaleR = 'log';
          xscaleI = 'log';
        otherwise
          error('### Unknown plot type for complex data');
      end
    end
    
    %------- Axis properties
        
    % Set ylabel    
    c = 1+(j-1)*2;
    if c<=length(ylabels)
      if ~isempty(ylabels{c})
        ylstrR =  ylabels{c};
      else
        ylstrR = ylabelr; 
      end
    else
      ylstrR = ylabelr;
    end
    if c<length(ylabels)
      if ~isempty(ylabels{c+1})
        ylstrI =  ylabels{c+1};
      else
        ylstrI = ylabeli;
      end
    else
      ylstrI = ylabeli;
    end    
    if ~isempty(ymath)
      ymath = strrep(ymath, 'y', sprintf('%s', a.data.yunits));
      ylstrR = [ylstrR ' [' ymath ']' ];
    else
      ylstrR = [ylstrR ' [' a.data.yunits ']' ];
    end
    ylabel(tsax_r, ylstrR);
    if ishandle(tsax_i)
      ylabel(tsax_i, ylstrI);
    end
    
    % Set xlabel
    if j<=length(xlabels) && ~isempty(xlabels{j})
        xlstr =  xlabels{j};
    else
      xlstr = find(pl, 'XLabel');
    end    
    if ~isempty(xmath)
      xmath = strrep(xmath, 'x', sprintf('%s', a.data.xunits));
      xlstr = [xlstr ' [' xmath ']' ];
    else
      xlstr = [xlstr ' [' a.data.xunits ']' ];
    end
    xlabel(tsax_r, xlstr);
    if ishandle(tsax_i)
      xlabel(tsax_i, xlstr);
    end    

    % Set grid on or off
    grid(tsax_r, 'on');
    if ishandle(tsax_i)
      grid(tsax_i, 'on');
    end
    
    % Set Y scale
    c = 1+(j-1)*2;
    if c<=length(yscales)
      if ~isempty(yscales{c})
        yscaleR =  yscales{c};
      end
    end
    if c<length(yscales)
      if ~isempty(yscales{c+1})
        yscaleI =  yscales{c+1};
      end
    end        
    set(tsax_r, 'YScale', yscaleR);
    if ishandle(tsax_i)
      set(tsax_i, 'YScale', yscaleI);
    end
    
    % Set X scale
    c = 1+(j-1)*2;
    if c<=length(xscales)
      if ~isempty(xscales{c})
        xscaleR =  xscales{c};
      end
    end
    if c<length(xscales)
      if ~isempty(xscales{c+1})
        xscaleI =  xscales{c+1};
      end
    end        
    set(tsax_r, 'XScale', xscaleR);
    if ishandle(tsax_i)
      set(tsax_i, 'XScale', xscaleI);
    end
    
    % Set Y range
    c = 1+(j-1)*2;
    if c<=length(yranges)
      if ~isempty(yranges{c})
        set(tsax_r, 'YLim', yranges{c});
      end
    end
    if c<length(yranges)
      if ~isempty(yranges{c+1})
        if ishandle(tsax_i)
          set(tsax_i, 'YLim', yranges{c+1});
        end
      end
    end        
    
    % Set X range
    c = 1+(j-1)*2;
    if c<=length(xranges)
      if ~isempty(xranges{c})
        set(tsax_r, 'XLim', xranges{c});
      end
    end
    if c<length(xranges)
      if ~isempty(xranges{c+1})
        if ishandle(tsax_i)
          set(tsax_i, 'XLim', xranges{c+1});
        end
      end
    end        
        
    %------- line properties
    
    % Set line color
    if isreal(y)
      set(tsli(end), 'Color', col);
    else
      set(tsli(end-1), 'Color', col);
      set(tsli(end), 'Color', col);
    end
    
    % Set line style
    if j<=length(linestyles) && ~isempty(linestyles{j})
      if isreal(y)
        set(tsli(end), 'LineStyle', linestyles{j});
      else
        set(tsli(end-1), 'LineStyle', linestyles{j});
        set(tsli(end), 'LineStyle', linestyles{j});
      end
    end
    
    % Set line widths    
    if j<=length(linewidths) && ~isempty(linewidths(j))
      if isreal(y)
        set(tsli(end), 'LineWidth', linewidths(j));
      else
        set(tsli(end-1), 'LineWidth', linewidths(j));
        set(tsli(end), 'LineWidth', linewidths(j));
      end
    end
    
    % Set legend string
    lstr = '';
    if legendsOn
      if j<=length(legends) && ~isempty(legends{j})
        lstr = legends{j};
      else
        lstr = ltpda_label(a.name);
      end
    end
    legendStr = [legendStr cellstr(lstr)];

    % Set the legend now if we can
    if legendsOn
      if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
        legend(tsax_r, legendStr{end});
      end
    end

  end % End loop over AOs
  
  % Process legends for stacked plots
  if legendsOn
    if strcmp(arrangement, 'stacked')
      h = legend(tsax_r, legendStr);
      set(h, 'FontSize', 10)
    end
  end
  
end

% Set outputs
if nargout > 0
  varargout{1} = tsfig;
end
if nargout > 1
  varargout{2} = tsax;
end
if nargout == 3
  varargout{3} = tsli;
end
if nargout > 3
  error('### Too many output arguments');
end

%--------------------------------------------------------------------------
% Plot tsdata and xydata objects
%
function varargout = xy_plot(varargin)

aos = varargin{1};
pl  = varargin{2};

% Extract parameters
arrangement = find(pl, 'Arrangement');
colors      = find(pl, 'Colors');
linestyles  = find(pl, 'LineStyles');
linewidths  = find(pl, 'LineWidths');
legends     = find(pl, 'Legends');
ylabels     = find(pl, 'YLabels');
xlabels     = find(pl, 'XLabels');
xmaths      = find(pl, 'XMaths');
ymaths      = find(pl, 'YMaths');

% check whether we want legends or not
if iscell(legends)
  legendsOn = 1;
else
  if strcmpi(legends, 'off')
    legendsOn = 0;
  else
    legendsOn = 1;
    legends = [];
  end
end

if ~iscell(linestyles), linestyles = {linestyles}; end
if ~iscell(legends), legends = {legends}; end
if ~iscell(ylabels), ylabels = {ylabels}; end
if ~iscell(xlabels), xlabels = {xlabels}; end
if ~iscell(xmaths), xmaths = {xmaths}; end
if ~iscell(ymaths), ymaths = {ymaths}; end


% collect figure handles
tsfig = [];
tsax  = [];
tsli  = [];

% Legend holder
legendStr = [];

if ~isempty(aos)

  % Now loop over AOs
  Na = length(aos);
  for j=1:Na
    
    % Get this AO
    a = aos(j);
    
    % what figures do we need?
    switch arrangement
      case 'single'        
        
        tsfig = [tsfig figure];
        tsax = subplot(1,1,1);
        col = colors{1};
        
      case 'stacked'
        
        if j==1, tsfig = figure; end
        tsax = subplot(1,1,1);
        col = colors{mod(j-1,length(colors))+1};
        hold on;
        
      case 'subplots'
        
        if j == 1, tsfig = figure; end
        tsax = [tsax subplot(Na, 1, j)];
        col = colors{1};
        
      otherwise
        error('### Unknown plot arrangement');
    end

    %------- Apply math functions
    x = a.data.x;
    y = a.data.y;
    
    ymath = '';
    if j<=length(ymaths)
      if ~isempty(ymaths{j})
        eval(sprintf('y = %s;', ymaths{j}));
        ymath = ymaths{j};
      end
    end
    xmath = '';
    if j<=length(xmaths)
      if ~isempty(xmaths{j})
        eval(sprintf('x = %s;', xmaths{j}));
        xmath = xmaths{j};
      end
    end
    
    %------- Plot the data
    
    tsli = [tsli plot(tsax(end), x, y)];
    
    %------- Axis properties
        
    % Set ylabel
    if j<=length(ylabels) && ~isempty(ylabels{j})
        ylstr =  ylabels{j};
    else
      ylstr = find(pl, 'YLabel');
    end    
    if ~isempty(ymath)
      ymath = strrep(ymath, 'y', sprintf('%s', a.data.yunits));
      ylstr = [ylstr ' [' ymath ']' ];
    else
      ylstr = [ylstr ' [' a.data.yunits ']' ];
    end
    ylabel(ylstr);
    
    % Set xlabel
    if j<=length(xlabels) && ~isempty(xlabels{j})
        xlstr =  xlabels{j};
    else
      xlstr = find(pl, 'XLabel');
    end    
    if ~isempty(xmath)
      xmath = strrep(xmath, 'x', sprintf('%s', a.data.xunits));
      xlstr = [xlstr ' [' xmath ']' ];
    else
      xlstr = [xlstr ' [' a.data.xunits ']' ];
    end
    xlabel(xlstr);
    
    
    % Set grid on or off
    grid(tsax(end), 'on');
    
    %------- line properties
    
    % Set line color
    set(tsli(end), 'Color', col);
    
    % Set line style
    if j<=length(linestyles) && ~isempty(linestyles{j})
      set(tsli(end), 'LineStyle', linestyles{j});
    end
    
    % Set line widths    
    if j<=length(linewidths) && ~isempty(linewidths(j))
      set(tsli(end), 'LineWidth', linewidths(j));
    end
    
    % Set legend string
    lstr = '';
    if legendsOn
      if j<=length(legends) && ~isempty(legends{j})
        lstr = legends{j};
      else
        lstr = ltpda_label(a.name);
      end
    end
    legendStr = [legendStr cellstr(lstr)];
    
    % Set the legend now if we can
    if legendsOn
      if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
        legend(legendStr{end});
      end
    end
  end
  
  % Process legends for stacked plots
  if legendsOn
    if strcmp(arrangement, 'stacked')
      h = legend(legendStr);
      set(h, 'FontSize', 10)
    end
  end
  
end

% Set outputs
if nargout > 0
  varargout{1} = tsfig;
end
if nargout > 1
  varargout{2} = tsax;
end
if nargout == 3
  varargout{3} = tsli;
end
if nargout > 3
  error('### Too many output arguments');
end


%--------------------------------------------------------------------------
% Plot cdata objects
%
function varargout = y_plot(varargin)

aos = varargin{1};
pl  = varargin{2};

% Extract parameters
arrangement = find(pl, 'Arrangement');
colors      = find(pl, 'Colors');
linestyles  = find(pl, 'LineStyles');
linewidths  = find(pl, 'LineWidths');
legends     = find(pl, 'Legends');
ylabels     = find(pl, 'YLabels');
xlabels     = find(pl, 'XLabels');
xmaths      = find(pl, 'XMaths');
ymaths      = find(pl, 'YMaths');

% check whether we want legends or not
if iscell(legends)
  legendsOn = 1;
else
  if strcmp(legends, 'off')
    legendsOn = 0;
  else
    legendsOn = 1;
    legends = [];
  end
end

if ~iscell(linestyles), linestyles = {linestyles}; end
if ~iscell(legends), legends = {legends}; end
if ~iscell(ylabels), ylabels = {ylabels}; end
if ~iscell(xlabels), xlabels = {xlabels}; end
if ~iscell(xmaths), xmaths = {xmaths}; end
if ~iscell(ymaths), ymaths = {ymaths}; end

% collect figure handles
tsfig = [];
tsax  = [];
tsli  = [];

% Legend holder
legendStr = [];

if ~isempty(aos)

  % Now loop over AOs
  Na = length(aos);
  for j=1:Na
    
    % Get this AO
    a = aos(j);
    
    % what figures do we need?
    switch arrangement
      case 'single'        
        
        tsfig = [tsfig figure];
        tsax = subplot(1,1,1);
        col = colors{1};
        
      case 'stacked'
        
        if j==1, tsfig = figure; end
        tsax = subplot(1,1,1);
        col = colors{mod(j-1,length(colors))+1};
        hold on;
        
      case 'subplots'
        
        if j == 1, tsfig = figure; end
        tsax = [tsax subplot(Na, 1, j)];
        col = colors{1};
        
      otherwise
        error('### Unknown plot arrangement');
    end

    %------- Apply math functions
    x = 1:length(a.data.y);
    y = a.data.y;
    
    ymath = '';
    if j<=length(ymaths)
      if ~isempty(ymaths{j})
        eval(sprintf('y = %s;', ymaths{j}));
        ymath = ymaths{j};
      end
    end
    xmath = '';
    if j<=length(xmaths)
      if ~isempty(xmaths{j})
        eval(sprintf('x = %s;', xmaths{j}));
        xmath = xmaths{j};
      end
    end
    
    %------- Plot the data
    
    idcs = plot(tsax(end), x, y);
    tsli = [tsli idcs(1:end).'];
    
    %------- Axis properties
        
    % Set ylabel
    if j<=length(ylabels) && ~isempty(ylabels{j})
        ylstr =  ylabels{j};
    else
      ylstr = find(pl, 'YLabel');
    end    
    if ~isempty(ymath)
      ymath = strrep(ymath, 'y', sprintf('%s', a.data.yunits));
      ylstr = [ylstr ' [' ymath ']' ];
    else
      ylstr = [ylstr ' [' a.data.yunits ']' ];
    end
    ylabel(ylstr);
    
    % Set xlabel
    if j<=length(xlabels) && ~isempty(xlabels{j})
        xlstr =  xlabels{j};
    else
      xlstr = find(pl, 'XLabel');
    end    
    if ~isempty(xmath)
      xmath = strrep(xmath, 'x', sprintf('%s', a.data.xunits));
      xlstr = [xlstr ' [' xmath ']' ];
    else
      xlstr = [xlstr ' [' a.data.xunits ']' ];
    end
    xlabel(xlstr);
    
    
    % Set grid on or off
    grid(tsax(end), 'on');
    
    %------- line properties
    
    % Set line color
    set(tsli(end), 'Color', col);
    
    % Set line style
    if j<=length(linestyles) && ~isempty(linestyles{j})
      set(tsli(end), 'LineStyle', linestyles{j});
    end
    
    % Set line widths    
    if j<=length(linewidths)
      set(tsli(end), 'LineWidth', linewidths(j));
    end
    
    % Set legend string
    if legendsOn
      if j<=length(legends) && ~isempty(legends{j})
        legendStr = [legendStr legends(j)];
      else
        lstr = ltpda_label(a.name);
        legendStr = [legendStr cellstr(lstr)];
      end
    end
    
    % Set the legend now if we can
    if legendsOn
      if strcmp(arrangement, 'single') || strcmp(arrangement, 'subplots')
        legend(legendStr{end});
      end
    end
  end
  
  % Process legends for stacked plots
  if legendsOn
    if strcmp(arrangement, 'stacked')
      h = legend(legendStr);
      set(h, 'FontSize', 10)
    end
  end
  
end

% Set outputs
if nargout > 0
  varargout{1} = tsfig;
end
if nargout > 1
  varargout{2} = tsax;
end
if nargout == 3
  varargout{3} = tsli;
end
if nargout > 3
  error('### Too many output arguments');
end

%--------------------------------------------------------------------------
% Plot xyzdata objects
%
function varargout = xyz_plot(varargin)

aos = varargin{1};
pl  = varargin{2};

% Extract parameters
arrangement = find(pl, 'Arrangement');
colors      = find(pl, 'Colors');
linestyles  = find(pl, 'LineStyles');
linewidths  = find(pl, 'LineWidths');
legends     = find(pl, 'Legends');
zlabels     = find(pl, 'ZLabels');
ylabels     = find(pl, 'YLabels');
xlabels     = find(pl, 'XLabels');
xmaths      = find(pl, 'XMaths');
ymaths      = find(pl, 'YMaths');
zmaths      = find(pl, 'ZMaths');

% check whether we want legends or not
if iscell(legends)
  legendsOn = 1;
else
  if strcmp(legends, 'off')
    legendsOn = 0;
  else
    legendsOn = 1;
    legends = [];
  end
end

% collect figure handles
tsfig = [];
tsax  = [];
tsli  = [];

% Legend holder
legendStr = [];

if ~isempty(aos)

  % Now loop over AOs
  Na = length(aos);
  for j=1:Na
    
    % Get this AO
    a = aos(j);
    
    % what figures do we need?
    switch arrangement
      case 'single'        
        
        tsfig = [tsfig figure];
        tsax = subplot(1,1,1);
                
      case 'subplots'
        
        if j == 1, tsfig = figure; end
        tsax = [tsax subplot(Na, 1, j)];
        
      otherwise
        error('### Unknown plot arrangement');
    end

    %------- Apply math functions
    x = a.data.x;
    y = a.data.y;
    z = a.data.z;
    
    
    ymath = '';
    if j<=length(ymaths)
      if ~isempty(ymaths{j})
        eval(sprintf('y = %s;', ymaths{j}));
        ymath = ymaths{j};
      end
    end
    xmath = '';
    if j<=length(xmaths)
      if ~isempty(xmaths{j})
        eval(sprintf('x = %s;', xmaths{j}));
        xmath = xmaths{j};
      end
    end
    zmath = '';
    if j<=length(zmaths)
      if ~isempty(zmaths{j})
        eval(sprintf('z = %s;', zmaths{j}));
        zmath = zmaths{j};
      end
    end
    
    %------- Plot the data
    
    idcs = pcolor(x,y,z);
    tsli = [tsli idcs(1:end).'];
    
    % plot properties
    set(idcs, 'EdgeColor', 'none');
    
    %------- Axis properties
    
    % Reverse y-direction for spectrograms
    set(tsax(end), 'YDir', 'reverse');
    
    % Set ylabel
    if j<=length(ylabels) && ~isempty(ylabels{j})
        ylstr =  ylabels{j};
    else
      ylstr = find(pl, 'YLabel');
    end    
    if ~isempty(ymath)
      ymath = strrep(ymath, 'y', sprintf('%s', a.data.yunits));
      ylstr = [ylstr ' [' ymath ']' ];
    else
      ylstr = [ylstr ' [' a.data.yunits ']' ];
    end
    ylabel(ylstr);
    
    % Set xlabel
    if j<=length(xlabels) && ~isempty(xlabels{j})
        xlstr =  xlabels{j};
    else
      xlstr = find(pl, 'XLabel');
    end    
    if ~isempty(xmath)
      xmath = strrep(xmath, 'x', sprintf('%s', a.data.xunits));
      xlstr = [xlstr ' [' xmath ']' ];
    else
      xlstr = [xlstr ' [' a.data.xunits ']' ];
    end
    xlabel(xlstr);
    
    % Set grid on or off
    grid(tsax(end), 'on');
        
    % Set title string
    if ~strcmpi(legends, 'off')
      if j<=length(legends) && ~isempty(legends{j})
        legendStr = [legendStr legends(j)];
      else
        lstr = ltpda_label(a.name);
        legendStr = [legendStr cellstr(lstr)];
      end
    end
    
    % Set the legend now if we can
    tstr = legendStr{end};
    if legendsOn
      title(tstr);
    end
    
    % Set colorbars
    hc = colorbar('peer', tsax(end));
    if j<=length(zlabels)
      if ~isempty(zlabels{j})
        zlstr = zlabels{j};
      end
    else
      zlstr = find(pl, 'Zlabel');
    end
    if ~isempty(zmath), zlstr = [zlstr sprintf('\n%s', zmath)]; end    
    ylh = get(hc, 'YLabel');
    set(ylh, 'String', zlstr);
    set(ylh, 'Fontsize', get(tsax(end), 'Fontsize'))
    set(ylh, 'FontName', get(tsax(end), 'FontName'))
    set(ylh, 'FontAngle', get(tsax(end), 'FontAngle'))
    set(ylh, 'FontWeight', get(tsax(end), 'FontWeight'))
  end
end

% Set outputs
if nargout > 0
  varargout{1} = tsfig;
end
if nargout > 1
  varargout{2} = tsax;
end
if nargout == 3
  varargout{3} = tsli;
end
if nargout > 3
  error('### Too many output arguments');
end


%--------------------------------------------------------------------------
% Default Parameter Lists
%
function out = getDefaultPlist(varargin)

% list of available parameter sets
sets = {'tsdata', 'fsdata', 'cdata', 'xydata'};

% Get the LTPDA color set for lines
colors = getappdata(0,'ltpda_default_plot_colors');

if nargin == 0
  out = sets;
  return
end

set = varargin{1};

out = plist('Colors', colors, ...
  'Arrangement', 'stacked');

switch set
  case 'fsdata'
    out = append(out, 'type', 'fsdata', ...
                      'complexPlotType', 'absdeg', ...
                      'XLabel', 'Frequency');
  case 'tsdata'
    out = append(out, 'type', 'tsdata', ...
                      'Xlabel', 'Time', ...
                      'Ylabel', 'Amplitude');
  case 'xydata'
    out = append(out, 'type', 'xydata', ...
                      'Xlabel', 'X-data', ...
                      'Ylabel', 'Y-data', ...
                      'YMaths', '', ...
                      'XMaths', '');
  case 'xyzdata'
    out = plist('Colors', colors, 'Arrangement', 'single', ...
                      'type', 'xydata', ...
                      'Xlabel', 'Time', ...
                      'Ylabel', 'Frequency',...
                      'Zlabel', 'Amplitude', ...
                      'YMaths', '', ...
                      'ZMaths', '', ...
                      'XMaths', '');
  case 'cdata'
    out = append(out, 'type', 'tsdata', ...
                      'Xlabel', 'Index', ...
                      'Ylabel', 'Value');
  otherwise
    out = plist();
end


