function cfg = singleplotTFR(cfg, data)

% singleplotTFR plots the time-frequency representation of a single channel
% using the output of FREQANALYSIS or WAVELETANALYSIS.
%
% Use as:
%   SinglePlotTFR(cfg,data)
%
% data is produced by FREQANALYSIS or WAVELETANALYSIS.
% cfg structure contains all configurations details for the plotting
%
% cfg.baseline         = 'yes','no' or [time1 time2]        (default = 'no')
% cfg.baselinetype     = 'absolute' or 'relative'           (default = 'absolute')
% cfg.xlim             = 'maxmin' or [xmin xmax]            (default = 'maxmin')
% cfg.ylim             = 'maxmin' or [ymin ymax]            (default = 'maxmin')
% cfg.zlim             = 'maxmin','absmax' or [zmin zmax]   (default = 'maxmin')
% cfg.xparam           = 'time';
% cfg.yparam           = 'freq';
% cfg.channelindex     = channel number/array of channel numbers *
% cfg.channelname      = channel label/cell array of channel labels *
% cfg.fontsize         =
% cfg.interactive      = 'yes', 'no'                        (default = 'no')
%
% * In case cfg.channelindex or cfg.channelname contains more than 1 channel, data
% will be averaged across the selected channels.
%
% See freqbaseline on details/options on baselining
%
% See also:
%   singleplotER, multiplotER, multiplotTFR, topoplotER, topoplotTFR.

clf

% For backward compatibility with old data structures:
data = fixdimord(data);

% Set the defaults:
if ~isfield(cfg,'baseline'),       cfg.baseline = 'no';                end
if ~isfield(cfg,'baselinetype'),    cfg.baselinetype = 'absolute';     end
if ~isfield(cfg,'xlim'),            cfg.xlim = 'maxmin';               end
if ~isfield(cfg,'ylim'),            cfg.ylim = 'maxmin';               end
if ~isfield(cfg,'zlim'),            cfg.zlim = 'maxmin';               end
if ~isfield(cfg,'fontsize'),        cfg.fontsize = 8;                  end
if ~isfield(cfg,'interactive'),     cfg.interactive = 'no';            end

% Set x/y/zparam defaults according to data.dimord value:
if strcmp(data.dimord, 'chan_time')
  if ~isfield(cfg, 'xparam'),      cfg.xparam='time';                  end
  if ~isfield(cfg, 'yparam'),      cfg.yparam='';                      end
  if ~isfield(cfg, 'zparam'),      cfg.zparam='avg';                   end
elseif strcmp(data.dimord, 'chan_freq')
  if ~isfield(cfg, 'xparam'),      cfg.xparam='freq';                  end
  if ~isfield(cfg, 'yparam'),      cfg.yparam='';                      end
  if ~isfield(cfg, 'zparam'),      cfg.zparam='powspctrm';             end
elseif strcmp(data.dimord, 'chan_freq_time')
  if ~isfield(cfg, 'xparam'),      cfg.xparam='time';                  end
  if ~isfield(cfg, 'yparam'),      cfg.yparam='freq';                  end
  if ~isfield(cfg, 'zparam'),      cfg.zparam='powspctrm';             end
end

% Verify and correct cfg.channelindex / cfg.channelname usage:
if isfield(cfg,'channelindex') && isfield(cfg,'channelname')
  warning('You have defined both cfg.channelindex and cfg.channelname; cfg.channelname will be used');
  cfg = rmfield(cfg,'channelindex');
end
if ~isfield(cfg,'channelindex') && ~isfield(cfg,'channelname')
  warning ('No channel index or name specified, automatically selected channel 1.');
  cfg.channelindex = 1;
end

if isfield(cfg,'channelname')
  % Convert single channel name to single-element cell array:
  if ischar(cfg.channelname)
    cfg.channelname = {cfg.channelname};
  end
  cfg.channel = channelselection(cfg.channelname, data.label);

  if isempty(cfg.channel)
    error(['Channel(s) not found: ' join(',',cfg.channelname)]);
  else
    cfg.channelindex = match_str(data.label, cfg.channelname);
  end
end

% Apply baseline correction:
if ~strcmp(cfg.baseline, 'no')
  data = freqbaseline(cfg, data);
end

% Get physical x-axis range:
if strcmp(cfg.xlim,'maxmin')
  xmin = min(data.(cfg.xparam));
  xmax = max(data.(cfg.xparam));
else
  xmin = cfg.xlim(1);
  xmax = cfg.xlim(2);
end

% Find corresponding x-axis bins:
xidc = find(data.(cfg.xparam) >= xmin & data.(cfg.xparam) <= xmax);

% Align physical x-axis range to the array bins:
xmin = data.(cfg.xparam)(xidc(1));
xmax = data.(cfg.xparam)(xidc(end));

% Get physical y-axis range:
if strcmp(cfg.ylim,'maxmin')
  ymin = min(data.(cfg.yparam));
  ymax = max(data.(cfg.yparam));
else
  ymin = cfg.ylim(1);
  ymax = cfg.ylim(2);
end

% Find corresponding y-axis bins:
yidc = find(data.(cfg.yparam) >= ymin & data.(cfg.yparam) <= ymax);

% Align physical y-axis range to the array bins:
ymin = data.(cfg.yparam)(yidc(1));
ymax = data.(cfg.yparam)(yidc(end));

% Get TFR data averaged across selected channels, within the selected x/y-range:
TFR = squeeze(mean(data.powspctrm(cfg.channelindex,yidc,xidc), 1));

% Get physical z-axis range (color axis):
if strcmp(cfg.zlim,'maxmin')
  zmin = min(TFR(:));
  zmax = max(TFR(:));
elseif strcmp(cfg.zlim,'absmax')
  zmin = -max(abs(TFR(:)));
  zmax = max(abs(TFR(:)));
else
  zmin = cfg.zlim(1);
  zmax = cfg.zlim(2);
end

% Draw plot:
hold on;
imagesc(data.time(xidc), data.freq(yidc), TFR, [zmin,zmax]);
axis xy;
colorbar;

% Make the figure interactive:
if strcmp(cfg.interactive, 'yes')
  userData.hFigure = gcf;
  userData.hAxes = gca;
  for i=1:1 % no multiple selection regions
    userData.hSelection{i} = plot(mean([xmin xmax]),mean([ymin ymax]));
    set(userData.hSelection{i}, 'XData', mean([xmin xmax]));
    set(userData.hSelection{i}, 'YData', mean([ymin ymax]));
    set(userData.hSelection{i}, 'Color', [0 0 0]);
    set(userData.hSelection{i}, 'EraseMode', 'xor');
    set(userData.hSelection{i}, 'LineStyle', '--');
    set(userData.hSelection{i}, 'LineWidth', 1.5);
    set(userData.hSelection{i}, 'Visible', 'on');
    userData.range{i} = [];
  end
  userData.iSelection = 0;
  userData.plotType = 'singleplot';
  userData.selecting = 0;
  userData.selectionType = '';
  userData.selectAxes = 'xy';
  userData.lastClick = [];
  userData.cfg = cfg;
  userData.data = data;
  userData.chanX = [];
  userData.chanY = [];
  userData.chanLabels = [];
  tag = sprintf('%.5f', 10000 * rand(1));
  set(gcf, 'Renderer', 'opengl');
  set(gcf, 'Tag', tag);
  set(gcf, 'UserData', userData);
  set(gcf, 'WindowButtonMotionFcn', ['plotSelection(get(findobj(''Tag'', ''' tag '''), ''UserData''), 0);']);
  set(gcf, 'WindowButtonDownFcn', ['plotSelection(get(findobj(''Tag'', ''' tag '''), ''UserData''), 1);']);
  set(gcf, 'WindowButtonUpFcn', ['plotSelection(get(findobj(''Tag'', ''' tag '''), ''UserData''), 2);']);
end

if ~isfield(cfg,'channelname')
  cfg.channelname = data.label{cfg.channelindex};
end

if length(cfg.channelname) == 1
  title([char(cfg.channelname{1}) ' / ' num2str(cfg.channelindex)])
else
  title(sprintf('mean(%0s)', join(',',cfg.channelname)));
end

axis tight;
hold off;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function l = cellstrmatch(str,strlist)
l = [];
for k=1:length(strlist)
  if strcmp(char(str),char(strlist(k)))
    l = [l k];
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function t = join(separator,cells)
if length(cells)==0
  t = '';
  return;
end
t = char(cells{1});

for i=2:length(cells)
  t = [t separator char(cells{i})];
end
