% PLOTDATA - plot concatenated multichannel data epochs in two-column format
%
% Usage:   >> plotdata(data)
%          >> plotdata(data,frames)
%          >> plotdata(data,frames,limits,title,channames,colors,rtitle,ydir) 
%
% Necessary input:
%   data       = data consisting of consecutive epochs of (chans,frames) 
%
% Optional inputs:
%   frames     = time frames/points per epoch {default: 0 -> data length}
%  [limits]    = [xmin xmax ymin ymax]  (x's in ms) 
%                {default|0 (or both y's 0) -> use data limits)
%  'title'     = plot title {default|0 -> none}
%  'channames' = channel location file or structure (see READLOCS)
%                {default|0 -> channel numbers}
%  'colors'    = file of color codes, 3 chars per line  
%                ( '.' = space) {default|0 -> default color order}
%  'rtitle'    = right-side plot title {default|0 -> none}
%   ydir       = y-axis polarity (1 -> pos-up; -1 -> neg-up) 
%                {default|0 -> set from default YDIR in 'icadefs.m'}             
%
% Authors: Scott Makeig, Arnaud Delorme, Tzyy-Ping Jung, 
%          SCCN/INC/UCSD, La Jolla, 05-01-96 
%
% See also: PLOTTOPO, TIMTOPO, ENVTOPO, HEADPLOT, COMPMAP, EEGMOVIE

% Copyright (C) 05-01-96 Scott Makeig, Arnaud Delorme & Tzyy-Ping Jung, 
% SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. 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.
%
% 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.

% 5-1-96 from showerps.m  -sm from showerp.m -tpj
% 5-3-96 added default channel numbering, frames & title -sm
% 5-17-96 added nargin tests below -sm
% 5-21-96 added right titles -sm
% 6-29-96 removed Postscript file query -sm
% 7-22-96 restored lines to fill printed page with figure -sm
% 7-29-96 added [channumbers] option for channames argument. -sm
%         changed "channels" argument to "channames" in help statement above -sm
% 1-6-97  debugged min/max time and +/- printing -tpj & sm
% 3-3-97  restored previous Default axis parameters at end -sm
% 4-2-97  debugged 32-epoch plotting -sm
% 5-10-97 added no-args check -sm
% 5-20-97 read icadefs.m for MAXPLOTDATACHANS and MAXPLOTDATAEPOCHS -sm
% 6-23-97 use returns instead of errorcodes -sm
% 10-31-97 use normalized PaperUnits for US/A4 compatibility, 
%          fixed [xy]{min,max} printing, added clf, adding Clipping off,
%          fixed scaling, added limits tests -sm & ch
% 11-19-97 removed an 'orient' command that caused problems printing -sm
% 07-15-98 added 'ydir' arg, made pos-up the default -sm
% 07-24-98 fixed 'ydir' arg, and pos-up default -sm
% 01-02-99 added warning about frames not dividing data length -sm
% 02-19-99 debugged axis limits -sm
% 11-21-01 add compatibility to load .loc files for channames -ad
% 01-25-02 reformated help & license, added links -ad 
% 02-16-02 added axcopy -ad & sm
% 03-15-02 added readlocs and the use of eloc input structure -ad 
% 03-15-02 added smart axcopy -ad 

function plotdata(data,frames,limits,plottitle,channels,colors,righttitle,ydr)

if nargin < 1,
    help plotdata
    return
end

%
% Set defaults
%
FONTSIZE = 12;     % font size to use for labels
TICKFONTSIZE=12;   % font size to use for axis labels
icadefs;           % read MAXPLOTDATACHANS constant from icadefs.m
                   % read YDIR
if ~exist('YDIR')
    fprintf('YDIR not read from ''icadefs.m'' - plotting positive-up.\n');
    YDIR = 1;
end
DEFAULT_SIGN = YDIR;  % default to plotting positive-up (1) or negative-up (-1)
                      % Now, read sign from YDIR in icadefs.m
ISSPEC = 0;           % default - 0 = not spectral data, 1 = pos-only spectra

axcolor= get(0,'DefaultAxesXcolor'); % find what the default x-axis color is
plotfile = 'plotdata.ps';
ls_plotfile = 'ls -l plotdata.ps';

%
%%%%%%%%%%%%%%%%%%%%%%%%%% Substitute defaults for missing parameters %%%%%
%
SIGN = DEFAULT_SIGN; % set default ydir from YDIR in icadefs.m
if nargin < 8
   ydr = [];
end
if ~isempty(ydr)& ydr ~=0  % override default from commandline 
 if ydr == 1
   SIGN = 1;
 else
   SIGN = -1;
 end
end

if nargin < 7,
    righttitle = 0; 
end
if nargin < 6
    colors = 0;
end
if nargin < 5
    channels = [1:size(data,1)]; % default channames = 1:chans
end
if nargin < 4
    plottitle = 0; %CJH
end
limitset = 0;
if nargin < 3,
    limits = 0;
elseif length(limits)>1
    limitset = 1;
end
if nargin < 2,
    frames = 0;
end
    
%%%%%%%%%%%%%%%%%%%%%%%%%%% Test parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  [chans,framestotal]=size(data);             % data size
  if frames <=0,
    frames = framestotal;    % default
    datasets=1;
  elseif frames==1,
    fprintf('plotdata: cannot plot less than 2 frames per trace.\n');
    return
    datasets=1;
  else
    datasets = fix(framestotal/frames);        % number of traces to overplot
    if datasets*frames < framestotal
         fprintf('\nWARNING: %d points at end of data will not be plotted.\n',...
                    framestotal-datasets*frames);
    end
  end

  if chans>MAXPLOTDATACHANS,
    fprintf('plotdata: not set up to plot more than %d channels.\n',...
                       MAXPLOTDATACHANS);
    return
  end
  if datasets>MAXPLOTDATAEPOCHS 
      fprintf('plotdata: not set up to plot more than %d epochs.\n',...
                       MAXPLOTDATAEPOCHS);
    return
  end
  if datasets<1
      fprintf('plotdata: cannot plot less than 1 epoch!\n');
      return
  end
%
%%%%%%%%%%%%% Extend the size of the plotting area in the window %%%%%%%%%%%%
%
  curfig = gcf;
  h=figure(curfig);
  set(h,'Color',BACKCOLOR); % set the background color
  set(h,'PaperUnits','normalized'); % use percentages to avoid US/A4 difference
  set(h,'PaperPosition',[0.0235308 0.0272775 0.894169 0.909249]); % equivalent
  % orient portrait
  axis('normal');
%
%%%%%%%%%%%%%%%%%%%% Read the channel names %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  if isnumeric(channels) && channels(1)==0,
    channels = [1:size(data,1)];
  end
  if isnumeric(channels),
      channames = num2str(channels(:));                   %%CJH
  else
      [tmp channames] = readlocs(channels);
      channames = strvcat(channames{:});
  end;       
%    chid = fopen(channels,'r');
%    if chid <3,
%        fprintf('PLOTDATA: cannot open file %s.\n',channels);
%        return
%     end
%     if isempty( findstr( lower(channels), '.loc') )
%    		channames = fscanf(chid,'%s',[4 Inf]);
%    		channames = channames';
%     else
%        	channames = fscanf(chid,'%d %f %f  %s',[7 128]);
%    		channames = char(channames(4:7,:)');
%     end
%     ii = find(channames == '.');
%     channames(ii) = ' ';
    
    %channames = channames';
    %   [r c] = size(channames);
    %for i=1:r
    %    for j=1:c
    %        if channames(i,j)=='.',
    %            channames(i,j)=' ';
    %        end
    %    end
    %end
%    end; % setting channames

%
%%%%%%%%%%%%%%%%%%%%%%%%% Read the color names %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  if colors ~=0,
    if ~ischar(colors)
       fprintf('plotdata(): color file name must be a string.\n');
       return
    end
    cid = fopen(colors,'r');
    % fprintf('cid = %d\n',cid);
    if cid <3,
        fprintf('plotdata: cannot open file %s.\n',colors);
        return
    end
    colors = fscanf(cid,'%s',[3 Inf]);
    colors = colors';
       [r c] = size(colors);
    for i=1:r
        for j=1:c
            if colors(i,j)=='.',
                colors(i,j)=' ';
            end
        end
    end
  else % use default color order (no yellow!)
     colors =['r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  ';'r  ';'b  ';'g  ';'c  ';'m  '];
     colors = [colors; colors];  % make > 64 available
  end
  for c=1:size(colors,1)   % make white traces black unless axis color is white
    if colors(c,1)=='w' && axcolor~=[1 1 1]
         colors(c,1)='k';
    end
  end

%
%%%%%%%%%%%%%%%%%%%%%%% Read and adjust limits %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  if limits==0,      % == 0 or [0 0 0 0]
    xmin=0;
    xmax=frames-1;
    ymin=min(min(data));
    ymax=max(max(data));
    yrange = ymax-ymin;
    ymin = ymin - 0.00*yrange;
    ymax = ymax + 0.00*yrange;
  else
    if length(limits)~=4,
      fprintf( ...
       'plotdata: limits should be 0 or an array [xmin xmax ymin ymax].\n');
      return
    end
    xmin = limits(1);
    xmax = limits(2);
    ymin = limits(3);
    ymax = limits(4);
  end

  if xmax == 0 && xmin == 0,
    x = (0:1:frames-1);
    xmin = 0;
    xmax = frames-1;
  else
    dx = (xmax-xmin)/(frames-1);
    x=xmin*ones(1,frames)+dx*(0:frames-1); % compute x-values
  end
  if xmax<=xmin,
      fprintf('plotdata() - xmax must be > xmin.\n')
      return
  end

  if ymax == 0 && ymin == 0,
      ymax=double(max(max(data)));
      ymin=double(min(min(data)));
      yrange = ymax-ymin;
      % ymin = ymin - 0.00*yrange;
      % ymax = ymax + 0.00*yrange;
  end
  if ymax<=ymin,
      fprintf('plotdata() - ymax must be > ymin.\n')
      return
  end

  xlabel = 'Time (ms)';
  if ymin >= 0 && xmin >= 0,          % For all-positive (spectral) data
    ISSPEC = 1;
    SIGN = 1;
    fprintf('\nPlotting positive up. Assuming data are spectra.\n');
    xlabel = 'Freq (Hz)';
    ymin = 0;                        % plot positive-up
  end

%
%%%%%%%%%%%%%%%%%%%%%%%% Set up plotting environment %%%%%%%%%%%%%%%%%%%%%%%%%
%
  h = gcf;
  % set(h,'YLim',[ymin ymax]);       % set default plotting parameters
  % set(h,'XLim',[xmin xmax]);
  % set(h,'FontSize',18);
  % set(h,'DefaultLineLineWidth',1); % for thinner postscript lines
%
%%%%%%%%%%%%%%%%%%%%%%%%%% Print plot info %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  clf;   % clear the current figure

  % print plottitle over (left) sbplot 1
  if plottitle==0,
      plottitle = '';
  end
  if righttitle==0,
      righttitle = '';
  end
  
  if ~isempty(righttitle)
      sbplot(ceil(chans/2),2,2), h=gca;%title([righttitle], 'FontSize',FONTSIZE); % title plot and
      set(h,'FontSize',FONTSIZE);            % choose font size
      set(h,'YLim',[ymin ymax]);            % set default plotting parameters
      set(h,'XLim',[xmin xmax]);
  end

  msg = ['\nPlotting %d traces of %d frames with colors: '];
  for c=1:datasets
    msg = [msg  colors(mod(c-1,length(colors))+1,:)];
  end
  msg = [msg ' -> \n'];    % print starting info on screen . . .
  fprintf(...
    '\n  limits: [xmin,xmax,ymin,ymax] = [%4.1f %4.1f %4.2f %4.2f]\n',...
                xmin,xmax,ymin,ymax);
  fprintf(msg,datasets,frames);
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Plot traces %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

  xdiff=xmax-xmin;
  ydiff=ymax-ymin;

  for P=0:datasets-1, %  for each data epoch
      fprintf('\ntrace %d: ',P+1);

    for I=1:chans,        % for each data channel

        index=(2*((rem(I-1,ceil(chans/2))+1)))-1+floor(2*(I-1)/chans); 
                                      % = 1 3 5 .. 2 4 6 ..
                                      % plot down left side of page first
        h=sbplot(ceil(chans/2),2,index); h=gca;    
        pos = get(h,'position');
        set(h,'position',[pos(1)-pos(4)*0.5 pos(2), pos(3),pos(4)*2]); % increase sbplot-height

        hold on;                      
        set(h,'YLim',[ymin ymax]);    % set default plotting parameters
        set(h,'XLim',[xmin xmax]);
        
        axislcolor = get(gca,'Xcolor');   %%CJH
        
        %
        %%%%%%%%%%%%%%%%%%%%% Plot two-sided time-series data %%%%%%%%%%%%%%%%%%%
        %
        if ~ISSPEC % not spectral data
            
            ymin = double(ymin);
            ymax = double(ymax);

            if ymin == ymax, ymin = ymin-1; ymax = ymax+1; end
            plot(x,SIGN*data(I,1+P*frames:1+P*frames+frames-1),colors(mod(P,length(colors))+1));   
            
            if SIGN > 0
                axis([xmin xmax ymin ymax]);          % set axis bounds (pos up)
            else
                axis([xmin xmax -1*ymax -1*ymin]);     % set axis bounds (neg up)
            end
            
            if P==datasets-1,            % on last traces
                if I==floor((chans+1)/2),   % draw +/0 on lowest left plot
                    signx = double(xmin-0.04*xdiff);
                    
                    if SIGN > 0  % pos up
                        axis('off');hl=text(signx,ymin,num2str(ymin,3));        % text ymin
                        axis('off');hi=text(signx,ymax,['+' num2str(ymax,3)]);  % text +ymax
                    else         % neg up
                        axis('off');hl=text(signx,-1*ymin,num2str(ymin,3));        % text ymin
                        axis('off');hi=text(signx,-1*ymax,['+' num2str(ymax,3)]);  % text +ymax
                    end
                    set(hl,'FontSize',TICKFONTSIZE);         % choose font size
                    set(hl,'HorizontalAlignment','right','Clipping','off');
                    set(hi,'FontSize',TICKFONTSIZE);         % choose font size
                    set(hi,'HorizontalAlignment','right','Clipping','off');
                end
                
                if I==chans && limitset,    % draw timescale on lowest right plot
                    ytick = double(-ymax-0.25*ydiff);
                    
                    tick = [int2str(xmin)]; h=text(xmin,ytick,tick); % min time
                    set(h,'FontSize',TICKFONTSIZE);         % choose font size
                    set(h,'HorizontalAlignment','center',...
                          'Clipping','off');  % center text
                    
                    tick = [xlabel]; h=text(xmin+xdiff/2,ytick,tick); % xlabel
                    set(h,'FontSize',TICKFONTSIZE);         % choose font size
                    set(h,'HorizontalAlignment','center',...
                          'Clipping','off');  % center text
                    
                    tick = [int2str(xmax)]; h=text(xmax,ytick,tick); % max time
                    set(h,'FontSize',TICKFONTSIZE);         % choose font size
                    set(h,'HorizontalAlignment','center',...
                      'Clipping','off');  % center text
                end
        end
      %
      %%%%%%%%%%%%%%%%%%%%% Plot spectral data positive-up [0,ymax] %%%%%%%%%%%%%%%%%%%%%%%%
      %
      else % ISSPEC
        ymin=0;
        plot(x,SIGN*data(I,1+P*frames:1+P*frames+frames-1),colors(mod(P,length(colors))+1));   
        ymaxm = ymax;

        % ymin = 0.01;
        % ymaxm = 10.^ceil(log(ymax)/log(10.));
        % if ymaxm/2. > ymax,
        %    ymaxm = ymaxm/2.;
        % end

        axis([xmin xmax ymin ymaxm]);      % set axis values

        if P==datasets-1,                  % on last trace
         if I==floor((chans+1)/2),         % draw +/0 on lowest left plot
          signx = xmin-0.04*xdiff;

          axis('off');h=text(signx,ymax,['+' num2str(ymax,3)]); 
            set(h,'FontSize',TICKFONTSIZE);
            set(h,'HorizontalAlignment','right','Clipping','off');        

          axis('off');h=text(signx,0,'0'); 
            set(h,'FontSize',TICKFONTSIZE);
            set(h,'HorizontalAlignment','right','Clipping','off');    
         end

         if I==chans,                    % draw freq scale on lowest right plot
            ytick = -0.25*ymax;

          tick = [num2str(round(10*xmin)/10) ]; h=text(xmin,ytick,tick);
            set(h,'FontSize',TICKFONTSIZE);              
            set(h,'HorizontalAlignment','center','Clipping','off'); 

          tick = [xlabel]; h=text(xmin+xdiff/2,ytick,tick);
            set(h,'FontSize',TICKFONTSIZE); 
            set(h,'HorizontalAlignment','center','Clipping','off');

          tick = [num2str(round(10*xmax)/10) ]; h=text(xmax,ytick,tick);
            set(h,'FontSize',TICKFONTSIZE);             
            set(h,'HorizontalAlignment','center','Clipping','off');

        end; % if last chan
      end % if last data
     end; % if ~ISSPEC

      %%%%%%%%%%%%%%%%%%%%%%% Print channel names and lines %%%%%%%%%%%%%%%%%%%%%%%%%%

      if P==datasets-1 
          if ~ISSPEC
              axis('off');
              plot([0 0],[ymin ymax],'color',axislcolor); % draw vert %%CJH
                                                          % axis at time 0  
          else  % ISSPEC
              axis('off');plot([xmin xmin],[0 ymax],'color',axislcolor); 
          end  
          
          % secondx = 200;                                % draw second vert axis 
          % axis('off');plot([secondx secondx],[ymin ymax],'color',axislcolor); 
          
          axis('off');
          plot([xmin xmax],[0 0],'color',axislcolor);     % draw horizontal axis 
          
          if ~isempty(channels),                          % print channames
              if ~ISSPEC
                  if ymin <= 0 && ymax >= 0,
                  yht = 0;
                  else
                      yht = nan_mean(SIGN*data(I,1+P*frames:1+P*frames+frames-1));
                  end
                  axis('off'),h=text(xmin-0.04*xdiff,double(yht),[channames(I,:)]); 
                  set(h,'HorizontalAlignment','right');      % print before traces
                  set(h,'FontSize',FONTSIZE);                % choose font size
                  
                  % axis('off'),h=text(xmax+0.10*xdiff,yht,[channames(I,:)]);
                  %    set(h,'HorizontalAlignment','left');      % print after traces
                  
              else % ISSPEC
                  axis('off'),h=text(xmin-0.04*xdiff,ymax/2,[channames(I,:)]); 
                  set(h,'HorizontalAlignment','right');      % print before traces
                  set(h,'FontSize',FONTSIZE);                % choose font size
                  
                  % axis('off'),h=text(xmax+0.10*xdiff,ymax/2,[channames(I,:)]);
                  %    set(h,'HorizontalAlignment','left');      % print after traces
                  
              end
          end; 
      end; 
      
     fprintf(' %d',I);
    end; % subplot
  end; % dataset
  fprintf('\n');
%
%%%%%%%%%%%%%%%%%% Make printed figure fill page %%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  curfig = gcf;
  h=figure(curfig);
  % set(h,'PaperPosition',[0.2 0.3 7.6 10]); % stretch out the plot on the page
%
%%%%%%%%%%%%%%%%%% Restore plot environment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  % set(h,'DefaultAxesYLim',aylim);      % restore previous plotting parameters
  % set(h,'DefaultAxesXLim',axlim);
  % set(h,'DefaultAxesFontSize',axfont);

%%%%%%%%%%%%%%%%%% Add axcopy %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if plottitle
	h = textsc(plottitle, 'title');
	set(h, 'fontsize', FONTSIZE);
end
axcopy(gcf, 'axis on');

if 0,    % START DETOUR XXXXXXXXXXXXX
%
%%%%%%%%%%%%%%%%%% Save plot to disk if asked %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
   if  plotfile ~= '', %
     n=0; y=1;
     answer = input('plotdata: Save plot as Postscript file? (y/n) ');
     if answer==1,
         fprintf('\nSaving figure as %s ... ',plotfile);
         curfig = gcf;
         h=figure(curfig);
         % set(h,'PaperPosition',[0.2 0.3 7.6 10]); 
                                     % stretch out the plot on the page
         eval (['print -dpsc ' plotfile]);
         fprintf('saved. Move or remove file!\n');
         unix(ls_plotfile);
     end
   end
end       % END DETOUR XXXXXXXXXXXXX

function out = nan_mean(in)

    nans = find(isnan(in));
    in(nans) = 0;
    sums = sum(in);
    nonnans = ones(size(in));
    nonnans(nans) = 0;
    nonnans = sum(nonnans);
    nononnans = find(nonnans==0);
    nonnans(nononnans) = 1;
    out = sum(in)./nonnans;
    out(nononnans) = NaN;

