function [ PH CH colorScale] = plotSeries(varargin)
%
% [ PH CH colorList ] = plotSeries(AH,x,y,s,colormap,OPTIONS)
%
% Plots x and y data with each column of y color-coded according to scalar 
% values defined in s.  plotSeries is particularly useful to illustrate how
% a x-y dataset *changes* in response to some value, s.
%
% Colormap can be defined by a string or a four-column matrix.  When a string
% is used or the argument is left empty, the colormap spans all values of
% s, linearly.  When a four-column matrix is provided, the first column 
% corresponds to potential values of s, the other three define the corresponding 
% RGB values.  The RGB values used for each column of y are interpolated
% from the rows of colormap, so there is no requirement for the number of
% rows of colormap to match up w/ the length of s.
%
% If length(s) > 1, then a colorbar will be included as a legend for the 
% line coloring.
%
% Optional lineseries specifications (OPTIONS) will be applied to all
% plots.
%
% plotSeries outputs a list of plotHandles (PH), a colorbar handle, (CH),
% and the colorList used for the plot.  The colorList output can be used
% directly as the colormap argument for other calls to plotSeries,
% providing a mechanism to easily produce multiple plots using similar 
% coloring schemes.
%
%  Example (cut and paste into the command-line):
%
%  % Show how sinc function changes as a function of s
%  s = 1:10;
%  x = (-1:1e-3:1).';
%  y = sinc(x*s);
%  figure; plotSeries(x,y,s,'jet','LineWidth',2);
%  xlabel('x-values');ylabel('y-values');
%
%  Inputs:  AH         - [1x1]       [OPTIONAL]  Axes handle
%           x          - [NxS / Nx1] X-coordinate data
%           y          - [NxS]       Y-coordinate data
%           s          - [1xS]       Scalar value associated with each data series
%                                    (length(s) = size(y,2))
%           colormap   - [Cx4]       Colormap to use for dataset coloring.
%                                    Can be colormap string OR four-column
%                                    colormap with 1st column corresponding to 
%                                    potential s values and 3 remaining columns 
%                                    corresponding to color.  Note that the
%                                    colormap will be interpolated to find
%                                    the appropriate color for each
%                                    dataset. ([] for 'default' colormap)
%           OPTIONS    -             Optional arguments for plot command
%
%  Outputs: PH         - [Sx1] Plot handle
%           CH         - [1x1] Colorbar handle
%           colorScale - [Sx4] Colormap w/ 1st column corresponding to 
%                              s values and 3 remaining columns corresponding to color
% 
%  N - Number of x-y coordinates to plot for each dataset
%  S - Number of datasets
%  C - Number of colors provided in colormap
%  
% Copyright (c) 2011, Hidden Solutions, LLC
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
%    * Redistributions of source code must retain the above copyright
%      notice, this list of conditions and the following disclaimer.
%    * Redistributions in binary form must reproduce the above copyright
%      notice, this list of conditions and the following disclaimer in the
%      documentation and/or other materials provided with the distribution.
%    * Neither the name Hidden Solutions, LLC nor the names of any
%      contributors may be used to endorse or promote products derived from 
%      this software without specific prior written permission.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
% DISCLAIMED. IN NO EVENT SHALL HIDDEN SOLUTIONS, LLC BE LIABLE FOR ANY
% DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%
% Author: James S. Hall (Hidden Solutions, LLC)
% Date:   17 October 2011
%

% Determine axes handle
if numel(varargin{1}) == 1 && ishandle(varargin{1})
  % If provided, pop AH from list of arguments
  AH       = varargin{1};
  varargin = varargin(2:end);
else
  % Assign current axes
  AH = gca;
end

% Assign x,y,z arguments
x = varargin{1};
y = varargin{2};
z = varargin{3};

% Force to column vectors (if appropriate)
if size(y,1) == 1
  y = y(:);
end
if size(z,1) == 1
  z = z(:);
end

% Generate colorList for plots
if length(varargin)>3 && ~isempty(varargin{4})
  if ischar(varargin{4})
    % If string provided, use as name of colormap
    cmap       = colormap(varargin{4});
    colorScale = [((0:1/(size(cmap,1)-1):1).'*range(z))+min(z) cmap];
  elseif size(varargin{4},2) == 4
    % Assign colormap to axes
    colorScale = varargin{4};
  end
  % Assign colormap to axes
  colormap(AH,colorScale(:,2:4));
else
  % Use default colormap
  cmap       = colormap();
  colorScale = [((0:1/(size(cmap,1)-1):1).'*range(z))+min(z) cmap];
end

% Determine colors to use for each plot
if length(z) > 1
  % Sort colors for interp1
  [cSort cInd] = sort(colorScale(:,1));
  colorScale   = colorScale(cInd,:);
  colorList    = interp1(colorScale(:,1),colorScale(:,2:4),z,'linear',nan);
  % Force s values outside of colorScale(:,1) range to max/min colorScale
  colorList(isnan(colorList(:,1))&z<min(colorScale(:,1)),:) = repmat(colorScale(1,:),sum(isnan(colorList(:,1))&z<min(colorScale(:,1))),1);
  colorList(isnan(colorList(:,1))&z>max(colorScale(:,1)),:) = repmat(colorScale(end,:),sum(isnan(colorList(:,1))&z<min(colorScale(:,1))),1);
else
  % Only one s value provided, use for all plots
  colorList = repmat(colorScale(1,2:4),size(y,2),1);
end

% Plot data
PH = plot(AH,x,y,varargin{5:end});

% Color-code data
for pp = 1:length(PH)
  set(PH(pp),'Color',colorList(pp,:));
end

if length(z) > 1
  % Add colorbar
  caxis([min(z) max(z)]);
  CH = colorbar;
end

end

