% dipplot() - Visualize EEG equivalent-dipole locations and orientations
%             in the MNI average MRI head or in the BESA spherical head model.
% Usage:
%   >> dipplot( sources, 'key', 'val', ...);
%   >> [sources X Y Z XE YE ZE] = dipplot( sources, 'key', 'val', ...);
%
% Inputs:
%   sources   -  structure array of dipole information: can contain
%                either BESA or DIPFIT dipole information. BESA dipole
%                information are still supported but may disapear in the
%                future. For DIPFIT
%                   sources.posxyz: contains 3-D location of dipole in each
%                                   column. 2 rows indicate 2 dipoles.
%                   sources.momxyz: contains 3-D moments for dipoles above.
%                   sources.rv    : residual variance from 0 to 1.
%                   other fields  : used for graphic interface.
%
% Optional input:
%  'rvrange'  - [min max] or [max] Only plot dipoles with residual variace
%               within the given range. Default: plot all dipoles.
%  'summary'  - ['on'|'off'|'3d'] Build a summary plot with three views (top,
%               back, side). {default: 'off'}
%  'mri'      - Matlab file containing an MRI volume and a 4-D transformation
%               matrix to go from voxel space to electrode space:
%               mri.anatomy   contains a 3-D anatomical data array
%               mri.transfrom contains a 4-D homogenous transformation matrix.
%  'coordformat' - ['MNI'|'spherical'] Consider that dipole coordinates are in
%               MNI or spherical coordinates (for spherical, the radius of the
%               head is assumed to be 85 (mm)). See also function sph2spm().
%  'transform' - [real array] traditional transformation matrix to convert
%               dipole coordinates to MNI space. Default is assumed from
%               'coordformat' input above. Type help traditional for more
%               information.
%  'image'    - ['besa'|'mri'] Background image.
%               'mri' (or 'fullmri') uses mean-MRI brain images from the Montreal
%               Neurological Institute. This option can also contain a 3-D MRI
%               volume (dim 1: left to right; dim 2: anterior-posterior; dim 3:
%               superior-inferior). Use 'coregist' to coregister electrodes
%               with the MRI. {default: 'mri'}
%  'verbose' - ['on'|'off'] comment on operations on command line {default:
%  'on'}.
%  'plot'    - ['on'|'off'] only return outputs                  {default: 'off'}.
%
% Plotting options:
%  'color'    - [cell array of color strings or (1,3) color arrays]. For
%               exemple { 'b' 'g' [1 0 0] } gives blue, green and red.
%               Dipole colors will rotate through the given colors if
%               the number given is less than the number of dipoles to plot.
%               A single number will be used as color index in the jet colormap.
%  'view'     - 3-D viewing angle in cartesian coords.,
%               [0 0 1] gives a sagittal view, [0 -1 0] a view from the rear;
%               [1 0 0] gives a view from the side of the head.
%  'mesh'     - ['on'|'off'] Display spherical mesh. {Default is 'on'}
%  'meshdata' - [cell array|'file_name'] Mesh data in a cell array { 'vertices'
%               data 'faces' data } or a boundary element model filename (the
%               function will plot the 3rd mesh in the 'bnd' sub-structure).
%  'axistight' - ['on'|'off'] For MRI only, display the closest MRI
%               slide. {Default is 'off'}
%  'gui'      - ['on'|'off'] Display controls. {Default is 'on'} If gui 'off',
%               a new figure is not created. Useful for incomporating a dipplot
%               into a complex figure.
%  'num'      - ['on'|'off'] Display component number. Take into account
%               dipole size. {Default: 'off'}
%  'cornermri' - ['on'|'off'] force MRI images to the corner of the MRI volume
%               (usefull when background is not black). Default: 'off'.
%  'drawedges' - ['on'|'off'] draw edges of the 3-D MRI (black in axistight,
%                white otherwise.) Default is 'off'.
%  'projimg'  - ['on'|'off'] Project dipole(s) onto the 2-D images, for use
%               in making 3-D plots {Default 'off'}
%  'projlines' - ['on'|'off'] Plot lines connecting dipole with 2-D projection.
%                Color is dashed black for BESA head and dashed black for the
%                MNI brain {Default 'off'}
%  'projcol'   - [color] color for the projected line {Default is same as dipole}
%  'dipolesize' - Size of the dipole sphere(s). This option may also contain one
%               value per dipole {Default: 30}
%  'dipolelength' - Length of the dipole bar(s) {Default: 1}
%  'pointout' - ['on'|'off'] Point the dipoles outward. {Default: 'off'}
%  'sphere'   - [float] radius of sphere corresponding to the skin. Default is 1.
%  'spheres'  - ['on'|'off'] {default: 'off'} plot dipole markers as 3-D spheres.
%               Does not yet interact with gui buttons, produces non-gui mode.
%  'spheresize' - [real>0] size of spheres (if 'on'). {default: 5}
%  'normlen'  - ['on'|'off'] Normalize length of all dipoles. {Default: 'off'}
%  'dipnames' - [cell array] cell array of string with a name for each dipole (or
%               pair of dipole).
%  'holdon'   - ['on'|'off'] create a new dipplot figure or plot dipoles within an
%               an existing figure. Default is 'off'.
%
% Outputs:
%   sources   - EEG.source structure with two extra fiels 'mnicoord' and 'talcoord'
%               containing the MNI and talairach coordinates of the dipoles. Note
%               that for the BEM model, dipoles are already in MNI coordinates.
%   X,Y,Z     - Locations of dipole heads (Cartesian coordinates in MNI space).
%               If there is more than one dipole per components, the last dipole
%               is returned.
%   XE,YE,ZE  - Locations of dipole ends (Cartesian coordinates). The same
%               remark as above applies.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 1st July 2002
%
% Notes: See DIPFIT web tutorial at sccn.ucsd.edu/eeglab/dipfittut/dipfit.html
%        for more details about MRI co-registration etc...
%
% Example:
%  % define dipoles
%  sources(1).posxyz = [-59 48 -28];   % position for the first dipole
%  sources(1).momxyz = [  0 58 -69];   % orientation for the first dipole
%  sources(1).rv     = 0.036;          % residual variance for the first dipole
%  sources(2).posxyz = [74 -4 -38];    % position for the second dipole
%  sources(2).momxyz = [43 -38 -16]; % orientation for the second dipole
%  sources(2).rv     = 0.027;          % residual variance for the second dipole
%
%  % plot of the two dipoles (first in green, second in blue)
%  dipplot( sources, 'color', { 'g' 'b' });
%
%  % To make a stereographic plot
%  figure( 'position', [153 553 1067 421];
%  subplot(1,3,1); dipplot( sources, 'view', [43 10], 'gui', 'off');
%  subplot(1,3,3); dipplot( sources, 'view', [37 10], 'gui', 'off');
%
%  % To make a summary plot
%  dipplot( sources, 'summary', 'on', 'num', 'on');
%
% See also: eeglab(), dipfit()

% old options
% -----------
%  'std'      - [cell array] plot standard deviation of dipoles. i.e.
%               { [1:6] [7:12] } plot two elipsoids that best fit all the dipoles
%               from 1 to 6 and 7 to 12 with radius 1 standard deviation.
%               { { [1:6] 2 'linewidth' 2 } [7:12] } do the same but now the
%               first elipsoid is 2 standard-dev and the lines are thicker.

% Copyright (C) 2002 Arnaud Delorme
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% README -- Plotting strategy:
% - All buttons have a tag 'tmp' so they can be removed
% - The component-number buttons have 'userdata' equal to 'editor' and
%   can be found easily by other buttons find('userdata', 'editor')
% - All dipoles have a tag 'dipoleX' (X=their number) and can be made
%     visible/invisible
% - The gcf object 'userdat' field stores the handle of the dipole that
%     is currently being modified
% - Gca 'userdata' stores imqge names and position

function [outsources, XX, YY, ZZ, XO, YO, ZO] = dipplot( sourcesori, varargin )

    DEFAULTVIEW = [0 0 1];

    if nargin < 1
        help dipplot;
        return;
    end;

    % reading and testing arguments
    % -----------------------------
    sources = sourcesori;
    if ~isstruct(sources)
        updatedipplot(sources(1));
        % sources countain the figure handler
        return
   end;

    %                             key        type       range             default
    g = finputcheck( varargin, { 'color'     ''         []                  [];
                                 'axistight' 'string'   { 'on' 'off' }     'off';
                                 'coordformat' 'string' { 'MNI' 'spherical' 'CTF' 'auto' } 'auto';
                                 'drawedges' 'string'   { 'on' 'off' }     'off';
                                 'mesh'      'string'   { 'on' 'off' }     'off';
                                 'gui'       'string'   { 'on' 'off' }     'on';
                                 'summary'   'string'   { 'on2' 'on' 'off' '3d' }     'off';
                                 'verbose'   'string'   { 'on' 'off' }     'on';
                                 'view'      'real'     []                 [0 0 1];
                                 'rvrange'   'real'     [0 Inf]             [];
                                 'transform' 'real'     [0 Inf]             [];
                                 'normlen'   'string'   { 'on' 'off' }     'off';
                                 'num'       'string'   { 'on' 'off' }     'off';
                                 'cornermri' 'string'   { 'on' 'off' }     'off';
                                 'mri'       { 'string' 'struct' } []      '';
                                 'dipnames'   'cell'     []                  {};
                                 'projimg'   'string'   { 'on' 'off' }     'off';
                                 'projcol'   ''         []       [];
                                 'projlines' 'string'   { 'on' 'off' 'z' 'x' 'y' }     'off';
                                 'pointout'  'string'   { 'on' 'off' }     'off';
                                 'holdon'    'string'   { 'on' 'off' }     'off';
                                 'dipolesize' 'real'    [0 Inf]             30;
                                 'dipolelength' 'real'  [0 Inf]             1;
                                 'sphere'    'real'   [0 Inf]               1;
                                 'spheres'   'string'  {'on' 'off'}         'off';
                                 'links'     'real'   []                    [];
                                 'image'     { 'string' 'real' } []         'mri';
                                 'plot'      'string'   { 'on' 'off' }      'on';
                                 'meshdata'  { 'string' 'cell' } []         '' }, 'dipplot');
    %                             'std'       'cell'     []                  {};
    %                             'coreg'     'real'     []                  [];

    if isstr(g), error(g); end;
    if strcmpi(g.holdon, 'on'), g.gui = 'off'; end;
    if length(g.dipolesize) == 1, g.dipolesize = repmat(g.dipolesize, [1 length(sourcesori)]); end;

    g.zoom = 1500;

    if strcmpi(g.image, 'besa')
        error('BESA image not supported any more. Use EEGLAB version 4.512 or earlier. (BESA dipoles can still be plotted in MNI brain.)');
    end;

    % trying to determine coordformat
    % -------------------------------
    if ~isfield(sources, 'momxyz')
        g.coordformat = 'spherical';
    end;
    if strcmpi(g.coordformat, 'auto')
        if ~isempty(g.meshdata)
            g.coordformat = 'MNI';
            if strcmpi(g.verbose, 'on'),
                disp('Coordinate format unknown: using ''MNI'' since mesh data was provided as input');
            end
        else
            maxdiplen = 0;
            for ind = 1:length(sourcesori)
                maxdiplen = max(maxdiplen, max(abs(sourcesori(ind).momxyz(:))));
            end;
            if maxdiplen>2000
                if strcmpi(g.verbose, 'on'),
                    disp('Coordinate format unknown: using ''MNI'' because of large dipole moments');
                end
            else
                g.coordformat = 'spherical';
                if strcmpi(g.verbose, 'on'),
                    disp('Coordinate format unknown: using ''spherical'' since no mesh data was provided as input');
                end
            end;
        end;
    end;

    % axis image and limits
    % ---------------------
    dat.axistight  = strcmpi(g.axistight, 'on');
    dat.drawedges  = g.drawedges;
    dat.cornermri  = strcmpi(g.cornermri, 'on');
    radius = 85;

    % look up an MRI file if necessary
    % --------------------------------
    if isempty(g.mri)
        if strcmpi(g.verbose, 'on'),
            disp('No MRI file given as input. Looking up one.');
        end
        dipfitdefs;
        g.mri = template_models(1).mrifile;
    end;

    % read anatomical MRI using Fieldtrip and SPM2 functons
    % -----------------------------------------------------
    if isstr(g.mri);
        try,
            g.mri = load('-mat', g.mri);
            g.mri = g.mri.mri;
        catch,
            disp('Failed to read Matlab file. Attempt to read MRI file using function read_fcdc_mri');
            try,
                warning off;
                g.mri = read_fcdc_mri(g.mri);
                %g.mri.anatomy(find(g.mri.anatomy > 255)) = 255;
                %g.mri.anatomy = uint8(g.mri.anatomy);
                g.mri.anatomy = round(gammacorrection( g.mri.anatomy, 0.8));
                g.mri.anatomy = uint8(round(g.mri.anatomy/max(reshape(g.mri.anatomy, prod(g.mri.dim),1))*255));
                % WARNING: if using double instead of int8, the scaling is different
                % [-128 to 128 and 0 is not good]
                % WARNING: the transform matrix is not 1, 1, 1 on the diagonal, some slices may be
                % misplaced
                warning on;
            catch,
                error('Cannot load file using read_fcdc_mri');
            end;
        end;
    end;

    if strcmpi(g.coordformat, 'spherical')
         dat.sph2spm    = sph2spm;
    elseif strcmpi(g.coordformat, 'CTF')
        dat.sph2spm    = traditionaldipfit([0 0 0 0 0 0 10 -10 10]);
    else
        dat.sph2spm    = []; %traditional([0 0 0 0 0 pi 1 1 1]);
    end;

    if ~isempty(g.transform), dat.sph2spm = traditionaldipfit(g.transform);
    end;
    if isfield(g.mri, 'anatomycol')
        dat.imgs       = g.mri.anatomycol;
    else
        dat.imgs       = g.mri.anatomy;
    end;
    dat.transform  = g.mri.transform;

    % MRI coordinates for slices
    % --------------------------
    if ~isfield(g.mri, 'xgrid')
        g.mri.xgrid = [1:size(dat.imgs,1)];
        g.mri.ygrid = [1:size(dat.imgs,2)];
        g.mri.zgrid = [1:size(dat.imgs,3)];
    end;
    if strcmpi(g.coordformat, 'CTF')
        g.mri.zgrid = g.mri.zgrid(end:-1:1);
    end;

    dat.imgcoords = { g.mri.xgrid g.mri.ygrid g.mri.zgrid };
    dat.maxcoord  = [max(dat.imgcoords{1}) max(dat.imgcoords{2}) max(dat.imgcoords{3})];
    COLORMESH = 'w';
    BACKCOLOR = 'k';

    % point 0
    % -------
    [xx yy zz] = transform(0, 0, 0, dat.sph2spm); % nothing happens for BEM since dat.sph2spm is empty
    dat.zeroloc = [ xx yy zz ];

    % conversion
    % ----------
    if strcmpi(g.normlen, 'on')
        if isfield(sources, 'besaextori')
            sources = rmfield(sources, 'besaextori');
        end;
    end;
    if ~isfield(sources, 'besathloc') & strcmpi(g.image, 'besa') & ~is_sccn
        error(['For copyright reasons, it is not possible to use the BESA ' ...
               'head model to plot non-BESA dipoles']);
    end;

    if isfield(sources, 'besathloc')
        sources = convertbesaoldformat(sources);
    end;
    if ~isfield(sources, 'posxyz')
        sources = computexyzforbesa(sources);
    end;
    if ~isfield(sources, 'component')
        if strcmpi(g.verbose, 'on'),
            disp('No component indices, making incremental ones...');
        end
        for index = 1:length(sources)
            sources(index).component = index;
        end;
    end;

    % find non-empty sources
    % ----------------------
    noempt = cellfun('isempty', { sources.posxyz } );
    sources = sources( find(~noempt) );

    % transform coordinates
    % ---------------------
    outsources = sources;
    for index = 1:length(sources)
        sources(index).momxyz = sources(index).momxyz/1000;
    end;

    % remove 0 second dipoles if any
    % ------------------------------
    for index = 1:length(sources)
        if size(sources(index).momxyz,1) == 2
            if all(sources(index).momxyz(2,:) == 0)
                sources(index).momxyz = sources(index).momxyz(1,:);
                sources(index).posxyz = sources(index).posxyz(1,:);
            end;
        end;
    end;

    % remove sources with out of bound Residual variance
    % --------------------------------------------------
    if isfield(sources, 'rv') & ~isempty(g.rvrange)
        if length(g.rvrange) == 1, g.rvrange = [ 0 g.rvrange ]; end;
        for index = length(sources):-1:1
            if sources(index).rv < g.rvrange(1)/100 | sources(index).rv > g.rvrange(2)/100
                sources(index) = [];
            end;
        end;
    end;

    % color array
    % -----------
    if isempty(g.color)
        g.color = { 'g' 'b' 'r' 'm' 'c' 'y' };
        if strcmp(BACKCOLOR, 'w'), g.color = { g.color{:} 'k' }; end;
    end;
    g.color = g.color(mod(0:length(sources)-1, length(g.color)) +1);
    if ~isempty(g.color)
        g.color = strcol2real( g.color, jet(64) );
    end;
    if ~isempty(g.projcol)
        g.projcol = strcol2real( g.projcol, jet(64) );
        g.projcol = g.projcol(mod(0:length(sources)-1, length(g.projcol)) +1);
    else
        g.projcol = g.color;
        for index = 1:length(g.color)
            g.projcol{index} =  g.projcol{index}/2;
        end;
    end;

    % build summarized figure
    % -----------------------
    if strcmpi(g.summary, 'on') | strcmpi(g.summary, 'on2')
        figure;
        options = { 'gui', 'off', 'dipolesize', g.dipolesize/1.5,'dipolelength', g.dipolelength, 'sphere', g.sphere ...
                    'color', g.color, 'mesh', g.mesh, 'num', g.num, 'image', g.image 'normlen' g.normlen ...
                    'coordformat' g.coordformat 'mri' g.mri 'meshdata' g.meshdata 'axistight' g.axistight };
        pos1 = [0 0 0.5 0.5];
        pos2 = [0 0.5 0.5 .5];
        pos3 = [.5 .5 0.5 .5]; if strcmp(g.summary, 'on2'), tmp = pos1; pos1 =pos3; pos3 = tmp; end;
        axes('position', pos1);  newsources = dipplot(sourcesori, 'view', [1 0 0] , options{:}); axis off;
        axes('position', pos2); newsources = dipplot(sourcesori, 'view', [0 0 1] , options{:}); axis off;
        axes('position', pos3); newsources = dipplot(sourcesori, 'view', [0 -1 0], options{:}); axis off;
        axes('position', [0.5 0 0.5 0.5]);
        colorcount = 1;
        if isfield(newsources, 'component')
            for index = 1:length(newsources)
                if isempty(g.dipnames), tmpname = sprintf( 'Comp. %d', newsources(index).component);
                else                    tmpname = char(g.dipnames{index});
                end;
                talpos = newsources(index).talcoord;
                if strcmpi(g.coordformat, 'CTF')
                    textforgui(colorcount) = { sprintf( [ tmpname ' (RV:%3.2f%%)' ], 100*newsources(index).rv) };
                elseif size(talpos,1) == 1
                    textforgui(colorcount) = { sprintf( [ tmpname ' (RV:%3.2f%%; Tal:%d,%d,%d)' ], ...
                                                        100*newsources(index).rv, ...
                                                        round(talpos(1,1)), round(talpos(1,2)), round(talpos(1,3))) };
                else
                    textforgui(colorcount) = { sprintf( [ tmpname ' (RV:%3.2f%%; Tal:%d,%d,%d & %d,%d,%d)' ], ...
                                                        100*newsources(index).rv, ...
                                                        round(talpos(1,1)), round(talpos(1,2)), round(talpos(1,3)), ...
                                                        round(talpos(2,1)), round(talpos(2,2)), round(talpos(2,3))) };
                end;
                colorcount = colorcount+1;
            end;
            colorcount = colorcount-1;
            allstr = strvcat(textforgui{:});
            h = text(0,0.45, allstr);
            if colorcount >= 15, set(h, 'fontsize', 8);end;
            if colorcount >= 20, set(h, 'fontsize', 6);end;
            if strcmp(BACKCOLOR, 'k'), set(h, 'color', 'w'); end;
        end;
        axis off;
        return;
    elseif strcmpi(g.summary, '3d')
        options = { 'gui', 'off', 'dipolesize', g.dipolesize/1.5,'dipolelength', g.dipolelength, 'sphere', g.sphere, 'spheres', g.spheres ...
                    'color', g.color, 'mesh', g.mesh, 'num', g.num, 'image', g.image 'normlen' g.normlen ...
                    'coordformat' g.coordformat 'mri' g.mri 'meshdata' g.meshdata 'axistight' g.axistight };
        figure('position', [ 100 600 600 200 ]);
        axes('position', [-0.1 -0.1 1.2 1.2], 'color', 'k'); axis off; blackimg = zeros(10,10,3); image(blackimg);
        axes('position', [0   0 1/3 1], 'tag', 'rear'); dipplot(sourcesori, options{:}, 'holdon', 'on'); view([0 -1 0]);
        axes('position', [1/3 0 1/3 1], 'tag', 'top' ); dipplot(sourcesori, options{:}, 'holdon', 'on'); view([0  0 1]);
        axes('position', [2/3 0 1/3 1], 'tag', 'side'); dipplot(sourcesori, options{:}, 'holdon', 'on'); view([1 -0.01 0]);
        set(gcf, 'paperpositionmode', 'auto');
        return;
    end;

    % plot head graph in 3D
    % ---------------------
    if strcmp(g.gui, 'on')
        fig = figure('visible', g.plot);
        pos = get(gca, 'position');
        set(gca, 'position', [pos(1)+0.05 pos(2:end)]);
    end;
    indx = ceil(dat.imgcoords{1}(end)/2);
    indy = ceil(dat.imgcoords{2}(end)/2);
    indz = ceil(dat.imgcoords{3}(end)/2);
    if strcmpi(g.holdon, 'off')
        plotimgs( dat, [indx indy indz], dat.transform);

        set(gca, 'color', BACKCOLOR);
        %warning off; a = imread('besaside.pcx'); warning on;
        % BECAUSE OF A BUG IN THE WARP FUNCTION, THIS DOES NOT WORK (11/02)
        %hold on; warp([], wy, wz, a);
        % set camera target
        % -----------------

        % format axis (BESA or MRI)
        axis equal;
        set(gca, 'cameraviewanglemode', 'manual'); % disable change size
        camzoom(1.2^2);
        if strcmpi(g.coordformat, 'CTF'), g.view(2:3) = -g.view(2:3); end;
        view(g.view);
        %set(gca, 'cameratarget',   dat.zeroloc); % disable change size
        %set(gca, 'cameraposition', dat.zeroloc+g.view*g.zoom); % disable change size
        axis off;
    end;

    % plot sphere mesh and nose
    % -------------------------
    if strcmpi(g.holdon, 'off')
        if isempty(g.meshdata)
            SPHEREGRAIN = 20; % 20 is also Matlab default
            [x y z] = sphere(SPHEREGRAIN);
            hold on;
            [xx yy zz] = transform(x*0.085, y*0.085, z*0.085, dat.sph2spm);
            [xx yy zz] = transform(x*85   , y*85   , z*85   , dat.sph2spm);
            %xx = x*100;
            %yy = y*100;
            %zz = z*100;
            if strcmpi(COLORMESH, 'w')
                hh = mesh(xx, yy, zz, 'cdata', ones(21,21,3), 'tag', 'mesh'); hidden off;
        else
            hh = mesh(xx, yy, zz, 'cdata', zeros(21,21,3), 'tag', 'mesh'); hidden off;
            end;
        else
            try,
            if isstr(g.meshdata)
                tmp = load('-mat', g.meshdata);
                g.meshdata = { 'vertices' tmp.vol.bnd(1).pnt 'faces' tmp.vol.bnd(1).tri };
            end;
            hh = patch(g.meshdata{:}, 'facecolor', 'none', 'edgecolor', COLORMESH, 'tag', 'mesh');
            catch, disp('Unrecognize model file (probably CTF)'); end;
        end;

    end;

    %x = x*100*scaling; y = y*100*scaling; z=z*100*scaling;
    %h = line(xx,yy,zz); set(h, 'color', COLORMESH, 'linestyle', '--', 'tag', 'mesh');
    %h = line(xx,zz,yy); set(h, 'color', COLORMESH, 'linestyle', '--', 'tag', 'mesh');
    %h = line([0 0;0 0],[-1 -1.2; -1.2 -1], [-0.3 -0.7; -0.7 -0.7]);
    %set(h, 'color', COLORMESH, 'linewidth', 3, 'tag', 'noze');

    % determine max length if besatextori exist
    % -----------------------------------------
    sizedip = [];
    for index = 1:length(sources)
        sizedip = [ sizedip sources(index).momxyz(3) ];
    end;
    maxlength = max(sizedip);

    % diph = gca; % DEBUG
    % colormap('jet');
    % cbar
    % axes(diph);

    for index = 1:length(sources)
        nbdip = 1;
        if size(sources(index).posxyz, 1) > 1 & any(sources(index).posxyz(2,:)) nbdip = 2; end;

        % reorder dipoles for plotting
        if nbdip == 2
            if sources(index).posxyz(1,1) > sources(index).posxyz(2,1)
                tmp = sources(index).posxyz(2,:);
                sources(index).posxyz(2,:) = sources(index).posxyz(1,:);
                sources(index).posxyz(1,:) = tmp;
                tmp = sources(index).momxyz(2,:);
                sources(index).momxyz(2,:) = sources(index).momxyz(1,:);
                sources(index).momxyz(1,:) = tmp;
            end;
            if isfield(sources, 'active'),
                nbdip = length(sources(index).active);
            end;
        end;

        for dip = 1:nbdip

            multfactor = 1;
            x = sources(index).posxyz(dip,1);
            y = sources(index).posxyz(dip,2);
            z = sources(index).posxyz(dip,3);
            if strcmpi(g.normlen, 'on')
                len    = sqrt(sum(sources(index).momxyz(dip,:).^2));
                if strcmpi(g.coordformat, 'CTF'), len = len*10; end;
                if len ~= 0, multfactor = 15/len; end;
            else
                if strcmpi(g.coordformat, 'spherical')
                     multfactor = 100;
                else multfactor = 1.5;
                end;
            end;

            xo = sources(index).momxyz(dip,1)*g.dipolelength*multfactor;
            yo = sources(index).momxyz(dip,2)*g.dipolelength*multfactor;
            zo = sources(index).momxyz(dip,3)*g.dipolelength*multfactor;

            xc = 0;
            yc = 0;
            zc = 0;

            centvec = [xo-xc yo-yc zo-zc]; % vector pointing into center
            dipole_orient = [x+xo y+yo z+zo]/norm([x+xo y+yo z+zo]);
            c = dot(centvec, dipole_orient);

            if strcmpi(g.pointout,'on')
                if (c < 0) | (abs([x+xo,y+yo,z+zo]) < abs([x,y,z]))
                    xo1 = x-xo; % make dipole point outward from head center
                    yo1 = y-yo;
                    zo1 = z-zo;
                    %fprintf('invert because: %e  \n', c);
                else
                    xo1 = x+xo;
                    yo1 = y+yo;
                    zo1 = z+zo;
                    %fprintf('NO invert because: %e  \n', c);
                end
            else
                xo1 = x+xo;
                yo1 = y+yo;
                zo1 = z+zo;
                %fprintf('NO invert because: %e  \n', c);
            end

            %
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% draw dipole bar %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            %
            tag = [ 'dipole' num2str(index) ];

            % from spherical to electrode space
            % ---------------------------------
            [xx   yy   zz]   = transform(x,   y,   z,   dat.sph2spm); % nothing happens for BEM
            [xxo1 yyo1 zzo1] = transform(xo1, yo1, zo1, dat.sph2spm); % because dat.sph2spm = []

            if ~strcmpi(g.spheres,'on') % plot dipole direction lines
               h1 = line( [xx xxo1]', [yy yyo1]', [zz zzo1]');

            elseif g.dipolelength>0 % plot dipole direction cylinders with end cap patch

               [xc yc zc] = cylinder( 2, 10);
               [xs ys zs] = sphere(10);
               xc = [ xc; -xs(7:11,:)*2  ];
               yc = [ yc; -ys(7:11,:)*2  ];
               zc = [ zc; zs(7:11,:)/5+1 ];

               colorarray = repmat(reshape(g.color{index}, 1,1,3), [size(zc,1) size(zc,2) 1]);
               handles = surf(xc, yc, zc, colorarray, 'tag', tag, 'edgecolor', 'none', ...
                              'backfacelighting', 'lit', 'facecolor', 'interp', 'facelighting', ...
                              'phong', 'ambientstrength', 0.3);
               [xc yc zc] = adjustcylinder2( handles, [xx yy zz], [xxo1 yyo1 zzo1] );

               cx = mean(xc,2); %cx = [(3*cx(1)+cx(2))/4; (cx(1)+3*cx(2))/4];
               cy = mean(yc,2); %cy = [(3*cy(1)+cy(2))/4; (cy(1)+3*cy(2))/4];
               cz = mean(zc,2); %cz = [(3*cz(1)+cz(2))/4; (cz(1)+3*cz(2))/4];
               tmpx = xc - repmat(cx, [1 size(xc, 2)]);
               tmpy = yc - repmat(cy, [1 size(xc, 2)]);
               tmpz = zc - repmat(cz, [1 size(xc, 2)]);
               l=sqrt(tmpx.^2+tmpy.^2+tmpz.^2);
               warning('off', 'MATLAB:divideByZero');                       % this is due to a Matlab 2008b (or later)
               normals = reshape([tmpx./l tmpy./l tmpz./l],[size(tmpx) 3]); % in the rotate function in adjustcylinder2
               warning('off', 'MATLAB:divideByZero');                       % one of the z (the last row is not rotated)
               set( handles, 'vertexnormals', normals);

            end

            [xxmri   yymri   zzmri  ] = transform(xx,   yy,   zz,   pinv(dat.transform));
            [xxmrio1 yymrio1 zzmrio1] = transform(xxo1, yyo1, zzo1, pinv(dat.transform));
            dipstruct.mricoord  = [xxmri yymri zzmri];   % Coordinates in MRI space
            dipstruct.eleccoord = [ xx yy zz ];          % Coordinates in elec space
            dipstruct.posxyz    = sources(index).posxyz; % Coordinates in spherical space
            outsources(index).eleccoord(dip,:) = [xx yy zz];
            outsources(index).mnicoord(dip,:) = [xx    yy    zz];
            outsources(index).mricoord(dip,:) = [xxmri yymri zzmri];
            outsources(index).talcoord(dip,:) = mni2tal([xx yy zz]')';
            dipstruct.talcoord                = mni2tal([xx yy zz]')';

            % copy for output
            % ---------------
            XX(index) = xxmri;
            YY(index) = yymri;
            ZZ(index) = zzmri;
            XO(index) = xxmrio1;
            YO(index) = yymrio1;
            ZO(index) = zzmrio1;

            if isempty(g.dipnames)
                dipstruct.rv   = sprintf('%3.2f', sources(index).rv*100);
                dipstruct.name = sources(index).component;
            else
                dipstruct.rv   = sprintf('%3.2f', sources(index).rv*100);
                dipstruct.name = g.dipnames{index};
            end;
            if ~strcmpi(g.spheres,'on') % plot disk markers
               set(h1,'userdata',dipstruct,'tag',tag,'color','k','linewidth',g.dipolesize(index)/7.5);
               if strcmp(BACKCOLOR, 'k'), set(h1, 'color', g.color{index}); end;
            end

            %
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%% draw sphere or disk marker %%%%%%%%%%%%%%%%%%%%%%%%%
            %
            hold on;
            if strcmpi(g.spheres,'on') % plot spheres
                if strcmpi(g.projimg, 'on')
                    if strcmpi(g.verbose, 'on'),
                        disp('Warning: projections cannot be plotted for 3-D sphere');
                    end
                    %tmpcolor = g.color{index} / 2;
                    %h = plotsphere([xx yy zz], g.dipolesize/6, 'color', g.color{index}, 'proj', ...
                    %               [dat.imgcoords{1}(1) dat.imgcoords{2}(end) dat.imgcoords{3}(1)]*97/100, 'projcol', tmpcolor);

                    %set(h(2:end), 'userdata', 'proj', 'tag', tag);
                else
                    %h = plotsphere([xx yy zz], g.dipolesize/6, 'color', g.color{index});
                end;
                h = plotsphere([xx yy zz], g.dipolesize(index)/6, 'color', g.color{index});
                set(h(1), 'userdata', dipstruct, 'tag', tag);
                % cko: try to plot dipnames
                if ~isempty(g.dipnames)
                    try
                        text(xx,yy,zz,g.dipnames{index},'color',[0.99 0.99 0.99]);
                    catch
                    end
                end

            else % plot dipole markers
               h = plot3(xx,  yy,  zz);
               set(h, 'userdata', dipstruct, 'tag', tag, ...
                   'marker', '.', 'markersize', g.dipolesize(index), 'color', g.color{index});
            end

            %
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% project onto images %%%%%%%%%%%%%%%%%%%%%%%%%
            %
            [tmp1xx   tmp1yy   tmp1zz  ] = transform( xxmri  , yymri  , dat.imgcoords{3}(1), dat.transform);
            [tmp1xxo1 tmp1yyo1 tmp1zzo1] = transform( xxmrio1, yymrio1, dat.imgcoords{3}(1), dat.transform);
            [tmp2xx   tmp2yy   tmp2zz  ] = transform( xxmri  , dat.imgcoords{2}(end), zzmri  , dat.transform);
            [tmp2xxo1 tmp2yyo1 tmp2zzo1] = transform( xxmrio1, dat.imgcoords{2}(end), zzmrio1, dat.transform);
            [tmp3xx   tmp3yy   tmp3zz  ] = transform( dat.imgcoords{1}(1), yymri  , zzmri  , dat.transform);
            [tmp3xxo1 tmp3yyo1 tmp3zzo1] = transform( dat.imgcoords{1}(1), yymrio1, zzmrio1, dat.transform);

            if strcmpi(g.projimg, 'on') & strcmpi(g.spheres, 'off')
                tmpcolor = g.projcol{index};

                % project onto z axis
                tag = [ 'dipole' num2str(index) ];
                if ~strcmpi(g.image, 'besa')
                    h = line( [tmp1xx tmp1xxo1]', [tmp1yy tmp1yyo1]', [tmp1zz tmp1zzo1]');
                    set(h, 'userdata', 'proj', 'tag', tag, 'color','k', 'linewidth', g.dipolesize(index)/7.5);
                end;
                if strcmp(BACKCOLOR, 'k'), set(h, 'color', tmpcolor); end;
                h = plot3(tmp1xx,  tmp1yy,  tmp1zz);
                set(h, 'userdata', 'proj', 'tag', tag, ...
                       'marker', '.', 'markersize', g.dipolesize(index), 'color', tmpcolor);

                % project onto y axis
                tag = [ 'dipole' num2str(index) ];
                if ~strcmpi(g.image, 'besa')
                    h = line( [tmp2xx tmp2xxo1]', [tmp2yy tmp2yyo1]', [tmp2zz tmp2zzo1]');
                    set(h, 'userdata', 'proj', 'tag', tag, 'color','k', 'linewidth', g.dipolesize(index)/7.5);
                end;
                if strcmp(BACKCOLOR, 'k'), set(h, 'color', tmpcolor); end;
                h = plot3(tmp2xx,  tmp2yy,  tmp2zz);
                set(h, 'userdata', 'proj', 'tag', tag, ...
                       'marker', '.', 'markersize', g.dipolesize(index), 'color', tmpcolor);

                % project onto x axis
                tag = [ 'dipole' num2str(index) ];
                if ~strcmpi(g.image, 'besa')
                    h = line( [tmp3xx tmp3xxo1]', [tmp3yy tmp3yyo1]', [tmp3zz tmp3zzo1]');
                    set(h, 'userdata', 'proj', 'tag', tag, 'color','k', 'linewidth', g.dipolesize(index)/7.5);
                end;
                if strcmp(BACKCOLOR, 'k'), set(h, 'color', tmpcolor); end;
                h = plot3(tmp3xx,  tmp3yy,  tmp3zz);
                set(h, 'userdata', 'proj', 'tag', tag, ...
                       'marker', '.', 'markersize', g.dipolesize(index), 'color', tmpcolor);
            end;

            %
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% project onto axes %%%%%%%%%%%%%%%%%%%%%%%%%
            %
            if ~strcmpi(g.projlines, 'off')
                clear h;
                % project onto z axis
                if any(strcmpi(g.projlines, {'on','z'}))
                    tag = [ 'dipole' num2str(index) ];
                    h(1) = line( [xx tmp1xx]', [yy tmp1yy]', [zz tmp1zz]);
                    set(h(1), 'userdata', 'proj', 'linestyle', '--', ...
                        'tag', tag, 'color', g.color{index}, 'linewidth', max(1,g.dipolesize(index)/7.5/5));
                end

                % project onto x axis
                if any(strcmpi(g.projlines, {'on','x'}))
                    tag = [ 'dipole' num2str(index) ];
                    h(2) = line( [xx tmp2xx]', [yy tmp2yy]', [zz tmp2zz]);
                    set(h(2), 'userdata', 'proj', 'linestyle', '--', ...
                        'tag', tag, 'color', g.color{index}, 'linewidth', max(1,g.dipolesize(index)/7.5/5));
                end

                % project onto y axis
                if any(strcmpi(g.projlines, {'on','y'}))
                    tag = [ 'dipole' num2str(index) ];
                    h(3) = line( [xx tmp3xx]', [yy tmp3yy]', [zz tmp3zz]);
                    set(h(3), 'userdata', 'proj', 'linestyle', '--', ...
                        'tag', tag, 'color', g.color{index}, 'linewidth', max(1,g.dipolesize(index)/7.5/5));
                end

                if ~isempty(g.projcol)
                    set(h, 'color', g.projcol{index});
                end;
            end;
            %
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% draw text  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            %
            if isfield(sources, 'component')
                if strcmp(g.num, 'on')
                    h = text(xx,  yy,  zz, [ '  ' int2str(sources(index).component)]);
                    set(h, 'userdata', dipstruct, 'tag', tag, 'fontsize', g.dipolesize(index)/2 );
                    if ~strcmpi(g.image, 'besa'), set(h, 'color', 'w'); end;
                end;
            end;
        end;
    end;

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3-D settings
    if strcmpi(g.spheres, 'on')
        lighting phong;
        material shiny;
        camlight left;
        camlight right;
    end;

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% draw elipse for group of dipoles  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % does not work because of new scheme, have to be reprogrammed

    %if ~isempty(g.std)
    %    for index = 1:length(g.std)
    %        if ~iscell(g.std{index})
    %            plotellipse(sources, g.std{index}, 1, dat.tcparams, dat.coreg);
    %        else
    %            sc = plotellipse(sources, g.std{index}{1}, g.std{index}{2}, dat.tcparams, dat.coreg);
    %            if length( g.std{index} ) > 2
    %                set(sc, g.std{index}{3:end});
    %            end;
    %         end;
    %     end;
    % end;

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% buttons %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    nbsrc = int2str(length(sources));
    cbmesh = [ 'if get(gcbo, ''userdata''), ' ...
               '    set(findobj(''parent'', gca, ''tag'', ''mesh''), ''visible'', ''off'');' ...
               '    set(gcbo, ''string'', ''Mesh on'');' ...
               '    set(gcbo, ''userdata'', 0);' ...
               'else,' ...
               '    set(findobj(''parent'', gca, ''tag'', ''mesh''), ''visible'', ''on'');' ...
               '    set(gcbo, ''string'', ''Mesh off'');' ...
               '    set(gcbo, ''userdata'', 1);' ...
               'end;' ];
    cbplot = [ 'if strcmpi(get(gcbo, ''string''), ''plot one''),' ...
               '    for tmpi = 1:' nbsrc ',' ...
               '        set(findobj(''parent'', gca, ''tag'', [ ''dipole'' int2str(tmpi) ]), ''visible'', ''off'');' ...
               '    end; clear tmpi;' ...
               '    dipplot(gcbf);' ...
               '    set(gcbo, ''string'', ''Plot all'');' ...
                   'else,' ...
               '    for tmpi = 1:' nbsrc ',' ...
               '        set(findobj(''parent'', gca, ''tag'', [ ''dipole'' int2str(tmpi) ]), ''visible'', ''on'');' ...
               '    end; clear tmpi;' ...
               '    set(gcbo, ''string'', ''Plot one'');' ...
               'end;' ];
    cbview = [ 'tmpuserdat = get(gca, ''userdata'');' ...
               'if tmpuserdat.axistight, ' ...
               '    set(gcbo, ''string'', ''Tight view'');' ...
               'else,' ...
               '    set(gcbo, ''string'', ''Loose view'');' ...
               'end;' ...
               'tmpuserdat.axistight = ~tmpuserdat.axistight;' ...
               'set(gca, ''userdata'', tmpuserdat);' ...
               'clear tmpuserdat;' ...
               'dipplot(gcbf);' ];
    viewstring = fastif(dat.axistight, 'Loose view', 'Tight view');
    enmesh     = fastif(isempty(g.meshdata) & strcmpi(g.coordformat, 'MNI'), 'off', 'on');
    if strcmpi(g.coordformat, 'CTF'), viewcor = 'view([0 1 0]);';  viewtop = 'view([0 0 -1]);'; vis = 'off';
    else                              viewcor = 'view([0 -1 0]);'; viewtop = 'view([0 0 1]);';  vis = 'on';
    end;

    h = uicontrol( 'unit', 'normalized', 'position', [0 0  .15 1], 'tag', 'tmp', ...
                   'style', 'text', 'string',' ');
    h = uicontrol( 'unit', 'normalized', 'position', [0 0 .15 .05], 'tag', 'tmp', ...
                       'style', 'pushbutton', 'fontweight', 'bold', 'string', 'No controls', 'callback', ...
                   'set(findobj(''parent'', gcbf, ''tag'', ''tmp''), ''visible'', ''off'');');
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.05 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Top view', 'callback', viewtop);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.1 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Coronal view', 'callback', viewcor);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.15 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Sagittal view', 'callback', 'view([1 0 0]);');
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.2  .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', viewstring, 'callback', cbview);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.25 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Mesh on', 'userdata', 0, 'callback', ...
                   cbmesh, 'enable', enmesh, 'visible', vis );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.3 .15 .05], 'tag', 'tmp', ...
                   'style', 'text', 'string', 'Display:','fontweight', 'bold' );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.35 .15 .02], 'tag', 'tmp',...
                   'style', 'text', 'string', '');
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.37 .15 .05], 'tag', 'tmp','userdata', 'z',...
                   'style', 'text', 'string', 'Z:', 'visible', vis );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.42 .15 .05], 'tag', 'tmp','userdata', 'y', ...
                   'style', 'text', 'string', 'Y:', 'visible', vis );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.47 .15 .05], 'tag', 'tmp', 'userdata', 'x',...
                   'style', 'text', 'string', 'X:', 'visible', vis );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.52 .15 .05], 'tag', 'tmp', 'userdata', 'rv',...
                   'style', 'text', 'string', 'RV:' );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.57 .15 .05], 'tag', 'tmp', 'userdata', 'comp', ...
                   'style', 'text', 'string', '');
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.62 .15 .05], 'tag', 'tmp', 'userdata', 'editor', ...
                   'style', 'edit', 'string', '1', 'callback', ...
                   [ 'dipplot(gcbf);' ] );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.67 .15 .05], 'tag', 'tmp', ...
                       'style', 'pushbutton', 'string', 'Keep|Prev', 'callback', ...
                   [ 'editobj = findobj(''parent'', gcf, ''userdata'', ''editor'');' ...
                     'set(editobj, ''string'', num2str(str2num(get(editobj, ''string''))-1));' ...
                     'tmpobj = get(gcf, ''userdata'');' ...
                     'eval(get(editobj, ''callback''));' ...
                     'set(tmpobj, ''visible'', ''on'');' ...
                     'clear editobj tmpobj;' ]);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.72 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Prev', 'callback',  ...
                   [ 'editobj = findobj(''parent'', gcf, ''userdata'', ''editor'');' ...
                     'set(editobj, ''string'', num2str(str2num(get(editobj, ''string''))-1));' ...
                     'eval(get(editobj, ''callback''));' ...
                     'clear editobj;' ]);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.77 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Next', 'callback', ...
                   [ 'editobj = findobj(''parent'', gcf, ''userdata'', ''editor'');' ...
                     'set(editobj, ''string'', num2str(str2num(get(editobj, ''string''))+1));' ...
                     'dipplot(gcbf);' ...
                     'clear editobj;' ]);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.82 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Keep|Next', 'callback', ...
                   [ 'editobj = findobj(''parent'', gcf, ''userdata'', ''editor'');' ...
                     'set(editobj, ''string'', num2str(str2num(get(editobj, ''string''))+1));' ...
                     'tmpobj = get(gcf, ''userdata'');' ...
                     'dipplot(gcbf);' ...
                     'set(tmpobj, ''visible'', ''on'');' ...
                     'clear editobj tmpobj;' ]);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.87 .15 .05], 'tag', 'tmp', ...
                   'style', 'pushbutton', 'string', 'Plot one', 'callback', cbplot);
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.92 .15 .05], 'tag', 'tmp', ...
                   'style', 'text', 'string', [num2str(length(sources)) ' dipoles:'], 'fontweight', 'bold' );
    h = uicontrol( 'unit', 'normalized', 'position', [0 0.97 .15 .05], 'tag', 'tmp', ...
                   'style', 'text', 'string', '');
    set(gcf, 'userdata', findobj('parent', gca, 'tag', 'dipole1'));

    dat.nbsources  = length(sources);
    set(gca, 'userdata', dat ); % last param=1 for MRI view tight/loose
    set(gcf, 'color', BACKCOLOR);

    if strcmp(g.gui, 'off') | strcmpi(g.holdon, 'on')
        set(findobj('parent', gcf, 'tag', 'tmp'), 'visible', 'off');
    end;
    if strcmp(g.mesh, 'off')
        set(findobj('parent', gca, 'tag', 'mesh'), 'visible', 'off');
    end;

    updatedipplot(gcf);

    rotate3d on;

    % close figure if necessary
    if strcmpi(g.plot, 'off')
        try, close(fig); catch, end;
    end;

    if strcmpi(g.holdon, 'on')
        box off;
        axis equal;
        axis off;
    end;

return;

% electrode space to MRI space
% ============================
function [x,y,z] = transform(x, y, z, transmat);

    if isempty(transmat), return; end;
    for i = 1:size(x,1)
        for j = 1:size(x,2)
            tmparray = transmat * [ x(i,j) y(i,j) z(i,j) 1 ]';
            x(i,j) = tmparray(1);
            y(i,j) = tmparray(2);
            z(i,j) = tmparray(3);
        end;
    end;

% does not work any more
% ----------------------
function sc = plotellipse(sources, ind, nstd, TCPARAMS, coreg);

    for i = 1:length(ind)
        tmpval(1,i) = -sources(ind(i)).posxyz(1);
        tmpval(2,i) = -sources(ind(i)).posxyz(2);
        tmpval(3,i) = sources(ind(i)).posxyz(3);
        [tmpval(1,i) tmpval(2,i) tmpval(3,i)] = transform(tmpval(1,i), tmpval(2,i), tmpval(3,i), TCPARAMS);
    end;

    % mean and covariance
    C = cov(tmpval');
    M = mean(tmpval,2);
    [U,L] = eig(C);

    % For N standard deviations spread of data, the radii of the eliipsoid will
    % be given by N*SQRT(eigenvalues).
    radii = nstd*sqrt(diag(L));

    % generate data for "unrotated" ellipsoid
    [xc,yc,zc] = ellipsoid(0,0,0,radii(1),radii(2),radii(3), 10);

    % rotate data with orientation matrix U and center M
    a = kron(U(:,1),xc); b = kron(U(:,2),yc); c = kron(U(:,3),zc);
    data = a+b+c;  n = size(data,2);
    x = data(1:n,:)+M(1); y = data(n+1:2*n,:)+M(2); z = data(2*n+1:end,:)+M(3);

    % now plot the rotated ellipse
    c = ones(size(z));
    sc = mesh(x,y,z);
    alpha(0.5)

function newsrc = convertbesaoldformat(src);
    newsrc = [];
    count = 1;
    countdip = 1;
    if ~isfield(src, 'besaextori'), src(1).besaextori = []; end;
    for index = 1:length(src)

        % convert format
        % --------------
        if isempty(src(index).besaextori), src(index).besaextori = 300; end; % 20 mm
        newsrc(count).possph(countdip,:) = [ src(index).besathloc src(index).besaphloc src(index).besaexent];
        newsrc(count).momsph(countdip,:) = [ src(index).besathori src(index).besaphori src(index).besaextori/300];

        % copy other fields
        % -----------------
        if isfield(src, 'stdX')
            newsrc(count).stdX = -src(index).stdY;
            newsrc(count).stdY = src(index).stdX;
            newsrc(count).stdZ = src(index).stdZ;
        end;
        if isfield(src, 'rv')
            newsrc(count).rv = src(index).rv;
        end;
        if isfield(src, 'elecrv')
            newsrc(count).rvelec = src(index).elecrv;
        end;
        if isfield(src, 'component')
            newsrc(count).component = src(index).component;
            if index ~= length(src) & src(index).component == src(index+1).component
                countdip = countdip + 1;
            else
                count = count + 1; countdip = 1;
            end;
        else
            count = count + 1; countdip = 1;
        end;
    end;

function src = computexyzforbesa(src);

    for index = 1:length( src )
        for index2 = 1:size( src(index).possph, 1 )

            % compute coordinates
            % -------------------
            postmp = src(index).possph(index2,:);
            momtmp = src(index).momsph(index2,:);

            phi      = postmp(1)+90; %% %%%%%%%%%%%%%%% USE BESA COORDINATES %%%%%
            theta    = postmp(2);    %% %%%%%%%%%%%%%%% USE BESA COORDINATES %%%%%
            phiori   = momtmp(1)+90; %% %%%%%%%%%%%% USE BESA COORDINATES %%%%%
            thetaori = momtmp(2);    %% %%%%%%%%%%%% USE BESA COORDINATES %%%%%
            % exentricities are in % of the radius of the head sphere
            [x y z]    = sph2cart(theta/180*pi, phi/180*pi, postmp(3)/1.2);
            [xo yo zo] = sph2cart(thetaori/180*pi, phiori/180*pi, momtmp(3)*5); % exentricity scaled for compatibility with DIPFIT
            src(index).posxyz(index2,:) = [-y x z];
            src(index).momxyz(index2,:) = [-yo xo zo];

        end;
     end;

% update dipplot (callback call)
% ------------------------------
function updatedipplot(fig)

   % find current dipole index and test for authorized range
   % -------------------------------------------------------
   dat     = get(gca, 'userdata');
   editobj = findobj('parent', fig, 'userdata', 'editor');
   tmpnum  = str2num(get(editobj(end), 'string'));
   if tmpnum < 1,             tmpnum = 1;             end;
   if tmpnum > dat.nbsources, tmpnum = dat.nbsources; end;
   set(editobj(end), 'string', num2str(tmpnum));

   % hide current dipole, find next dipole and show it
   % -------------------------------------------------
   set(get(gcf, 'userdata'), 'visible', 'off');
   newdip = findobj('parent', gca, 'tag', [ 'dipole' get(editobj(end), 'string')]);
   set(newdip, 'visible', 'on');
   set(gcf, 'userdata', newdip);

   % find all dipolar structures
   % ---------------------------
   index   = 1;
   count   = 1;
   for index = 1:length(newdip)
       if isstruct( get(newdip(index), 'userdata') )
           dip_mricoord(count,:) = getfield(get(newdip(index), 'userdata'), 'mricoord');
           count = count+1;
           foundind = index;
       end;
   end;

   % get residual variance
   % ---------------------
   if exist('foundind')
      tmp = get(newdip(foundind), 'userdata');
      tal = tmp.talcoord;
      if ~isstr( tmp.name )
           tmprvobj = findobj('parent', fig, 'userdata', 'comp'); set( tmprvobj(end), 'string', [ 'Comp: ' int2str(tmp.name) ] );
      else tmprvobj = findobj('parent', fig, 'userdata', 'comp'); set( tmprvobj(end), 'string', tmp.name );
      end;
      tmprvobj = findobj('parent', fig, 'userdata', 'rv');   set( tmprvobj(end), 'string', [ 'RV: ' tmp.rv '%' ] );
      tmprvobj = findobj('parent', fig, 'userdata', 'x');    set( tmprvobj(end), 'string', [ 'X tal: ' int2str(round(tal(1))) ]);
      tmprvobj = findobj('parent', fig, 'userdata', 'y');    set( tmprvobj(end), 'string', [ 'Y tal: ' int2str(round(tal(2))) ]);
      tmprvobj = findobj('parent', fig, 'userdata', 'z');    set( tmprvobj(end), 'string', [ 'Z tal: ' int2str(round(tal(3))) ]);
   end

   % adapt the MRI to the dipole depth
   % ---------------------------------
   delete(findobj('parent', gca, 'tag', 'img'));

   tmpdiv1 = dat.imgcoords{1}(2)-dat.imgcoords{1}(1);
   tmpdiv2 = dat.imgcoords{2}(2)-dat.imgcoords{2}(1);
   tmpdiv3 = dat.imgcoords{3}(2)-dat.imgcoords{3}(1);
   if ~dat.axistight
       [xx yy zz] = transform(0,0,0, pinv(dat.transform)); % elec -> MRI space
       indx = minpos(dat.imgcoords{1}-zz);
       indy = minpos(dat.imgcoords{2}-yy);
       indz = minpos(dat.imgcoords{3}-xx);
   else
       if ~dat.cornermri
           indx = minpos(dat.imgcoords{1} - mean(dip_mricoord(:,1))) - 3*tmpdiv1;
           indy = minpos(dat.imgcoords{2} - mean(dip_mricoord(:,2))) + 3*tmpdiv2;
           indz = minpos(dat.imgcoords{3} - mean(dip_mricoord(:,3))) - 3*tmpdiv3;
       else % no need to shift slice if not ploted close to the dipole
           indx = minpos(dat.imgcoords{1} - mean(dip_mricoord(:,1)));
           indy = minpos(dat.imgcoords{2} - mean(dip_mricoord(:,2)));
           indz = minpos(dat.imgcoords{3} - mean(dip_mricoord(:,3)));
       end;
   end;

   % middle of the brain
   % -------------------
   plotimgs( dat, [indx indy indz], dat.transform);
   %end;

% plot images (transmat is the uniform matrix MRI coords -> elec coords)
% ----------------------------------------------------------------------
function plotimgs(dat, mricoord, transmat);

    % loading images
    % --------------
    if ndims(dat.imgs) == 4 % true color data
        img1(:,:,3) = rot90(squeeze(dat.imgs(mricoord(1),:,:,3)));
        img2(:,:,3) = rot90(squeeze(dat.imgs(:,mricoord(2),:,3)));
        img3(:,:,3) = rot90(squeeze(dat.imgs(:,:,mricoord(3),3)));
        img1(:,:,2) = rot90(squeeze(dat.imgs(mricoord(1),:,:,2)));
        img2(:,:,2) = rot90(squeeze(dat.imgs(:,mricoord(2),:,2)));
        img3(:,:,2) = rot90(squeeze(dat.imgs(:,:,mricoord(3),2)));
        img1(:,:,1) = rot90(squeeze(dat.imgs(mricoord(1),:,:,1)));
        img2(:,:,1) = rot90(squeeze(dat.imgs(:,mricoord(2),:,1)));
        img3(:,:,1) = rot90(squeeze(dat.imgs(:,:,mricoord(3),1)));
    else
        img1 = rot90(squeeze(dat.imgs(mricoord(1),:,:)));
        img2 = rot90(squeeze(dat.imgs(:,mricoord(2),:)));
        img3 = rot90(squeeze(dat.imgs(:,:,mricoord(3))));

        if ndims(img1) == 2, img1(:,:,3) = img1; img1(:,:,2) = img1(:,:,1); end;
        if ndims(img2) == 2, img2(:,:,3) = img2; img2(:,:,2) = img2(:,:,1); end;
        if ndims(img3) == 2, img3(:,:,3) = img3; img3(:,:,2) = img3(:,:,1); end;
    end;

    % computing coordinates for planes
    % --------------------------------
    wy1 = [min(dat.imgcoords{2}) max(dat.imgcoords{2}); min(dat.imgcoords{2}) max(dat.imgcoords{2})];
    wz1 = [min(dat.imgcoords{3}) min(dat.imgcoords{3}); max(dat.imgcoords{3}) max(dat.imgcoords{3})];
    wx2 = [min(dat.imgcoords{1}) max(dat.imgcoords{1}); min(dat.imgcoords{1}) max(dat.imgcoords{1})];
    wz2 = [min(dat.imgcoords{3}) min(dat.imgcoords{3}); max(dat.imgcoords{3}) max(dat.imgcoords{3})];
    wx3 = [min(dat.imgcoords{1}) max(dat.imgcoords{1}); min(dat.imgcoords{1}) max(dat.imgcoords{1})];
    wy3 = [min(dat.imgcoords{2}) min(dat.imgcoords{2}); max(dat.imgcoords{2}) max(dat.imgcoords{2})];
    if dat.axistight & ~dat.cornermri
        wx1 = [ 1 1; 1 1]*dat.imgcoords{1}(mricoord(1));
        wy2 = [ 1 1; 1 1]*dat.imgcoords{2}(mricoord(2));
        wz3 = [ 1 1; 1 1]*dat.imgcoords{3}(mricoord(3));
    else
        wx1 =  [ 1 1; 1 1]*dat.imgcoords{1}(1);
        wy2 =  [ 1 1; 1 1]*dat.imgcoords{2}(end);
        wz3 =  [ 1 1; 1 1]*dat.imgcoords{3}(1);
    end;

    % transform MRI coordinates to electrode space
    % --------------------------------------------
    [ elecwx1 elecwy1 elecwz1 ] = transform( wx1, wy1, wz1, transmat);
    [ elecwx2 elecwy2 elecwz2 ] = transform( wx2, wy2, wz2, transmat);
    [ elecwx3 elecwy3 elecwz3 ] = transform( wx3, wy3, wz3, transmat);

    % ploting surfaces
    % ----------------
    options = { 'FaceColor','texturemap', 'EdgeColor','none', 'CDataMapping', ...
                'direct','tag','img', 'facelighting', 'none' };
    hold on;
    surface(elecwx1, elecwy1, elecwz1, img1(end:-1:1,:,:), options{:});
    surface(elecwx2, elecwy2, elecwz2, img2(end:-1:1,:,:), options{:});
    surface(elecwx3, elecwy3, elecwz3, img3(end:-1:1,:,:), options{:});
    %xlabel('x'); ylabel('y'); zlabel('z'); axis equal; dsaffd

    if strcmpi(dat.drawedges, 'on')
        % removing old edges if any
        delete(findobj( gcf, 'tag', 'edges'));
        if dat.axistight & ~dat.cornermri, col = 'k'; else col = [0.5 0.5 0.5]; end;
        h(1) = line([elecwx3(1) elecwx3(2)]', [elecwy3(1) elecwy2(1)]', [elecwz1(1) elecwz1(2)]'); % sagittal-transverse
        h(2) = line([elecwx3(1) elecwx2(3)]', [elecwy2(1) elecwy2(2)]', [elecwz1(1) elecwz1(2)]'); % coronal-tranverse
        h(3) = line([elecwx3(1) elecwx3(2)]', [elecwy2(1) elecwy2(2)]', [elecwz3(1) elecwz1(1)]'); % sagittal-coronal
        set(h, 'color', col, 'linewidth', 2, 'tag', 'edges');
    end;

    %%fill3([-2 -2 2 2], [-2 2 2 -2], wz(:)-1, BACKCOLOR);
    %%fill3([-2 -2 2 2], wy(:)-1, [-2 2 2 -2], BACKCOLOR);
    rotate3d on

function index = minpos(vals);
	vals(find(vals < 0)) = inf;
	[tmp index] = min(vals);

function scalegca(multfactor)
    xl = xlim; xf = ( xl(2) - xl(1) ) * multfactor;
    yl = ylim; yf = ( yl(2) - yl(1) ) * multfactor;
    zl = zlim; zf = ( zl(2) - zl(1) ) * multfactor;
    xlim( [ xl(1)-xf xl(2)+xf ]);
    ylim( [ yl(1)-yf yl(2)+yf ]);
    zlim( [ zl(1)-zf zl(2)+zf ]);

function color = strcol2real(colorin, colmap)
    if ~iscell(colorin)
        for index = 1:length(colorin)
            color{index} = colmap(colorin(index),:);
        end;
    else
        color = colorin;
        for index = 1:length(colorin)
            if isstr(colorin{index})
                switch colorin{index}
                 case 'r', color{index} = [1 0 0];
                 case 'g', color{index} = [0 1 0];
                 case 'b', color{index} = [0 0 1];
                 case 'c', color{index} = [0 1 1];
                 case 'm', color{index} = [1 0 1];
                 case 'y', color{index} = [1 1 0];
                 case 'k', color{index} = [0 0 0];
                 case 'w', color{index} = [1 1 1];
                 otherwise, error('Unknown color');
                end;
            end;
        end;
    end;

function x = gammacorrection(x, gammaval);
    x = 255 * (double(x)/255).^ gammaval;
    % image is supposed to be scaled from 0 to 255
    % gammaval = 1 is identity of course


clc;clear all;close all;
addpath ../test
addpath ..
addpath CM_Curve
%netStruct = load('../data/res52_drop0.75_batch16_psudo_label/net-epoch-25.mat');
%netStruct.net.layers(end-3)=[];
%netStruct.net.vars(178)=[];
%net = dagnn.DagNN.loadobj(netStruct.net);
%net.addLayer('feature',dagnn.Concat('dim',3),{'pool5','pool5_local'},{'pool5_fine'});
%net.mode = 'test' ;
%net.move('gpu') ;
rank_size = 2000;
%net.conserveMemory = false;
%im_mean = net.meta.normalization.averageImage;
%im_mean = imresize(im_mean,[224,224]);

%% add necessary paths
query_dir = '/DATACENTER/1/qxl/PRID/Market-1501/query/';% query directory
test_dir = '/DATACENTER/1/qxl/PRID/Market-1501/bounding_box_test/';% database directory
feature_dir = '/home/qxl/Desktop/';

%% calculate query features
Hist_query = importdata([feature_dir 'Hist_query.mat']);
nQuery = size(Hist_query, 2);
%nQuery = 100;
%% calculate database features
Hist_test = importdata([feature_dir 'Hist_test.mat']);
nTest = size(Hist_test, 2);
%nTest = 19732;
%% calculate the ID and camera for database images
mkdir('./data')
test_files = dir([test_dir '*.jpg']);
testID = zeros(length(test_files), 1);
testCAM = zeros(length(test_files), 1);
if ~exist('data/testID.mat')
    for n = 1:length(test_files)
        img_name = test_files(n).name;
        if strcmp(img_name(1), '-') % junk images
            testID(n) = -1;
            testCAM(n) = str2num(img_name(5));
        else
            %img_name
            testID(n) = str2num(img_name(1:4));
            testCAM(n) = str2num(img_name(7));
        end
    end
    save('data/testID.mat', 'testID');
    save('data/testCAM.mat', 'testCAM');
else
    testID = importdata('data/testID.mat');
    testCAM = importdata('data/testCAM.mat');
end

%% calculate the ID and camera for query images
query_files = dir([query_dir '*.jpg']);
queryID = zeros(length(query_files), 1);
queryCAM = zeros(length(query_files), 1);
if ~exist('data/queryID.mat')
    for n = 1:length(query_files)
        img_name = query_files(n).name;
        if strcmp(img_name(1), '-') % junk images
            queryID(n) = -1;
            queryCAM(n) = str2num(img_name(5));
        else
            queryID(n) = str2num(img_name(1:4));
            queryCAM(n) = str2num(img_name(7));
        end
    end
    save('data/queryID.mat', 'queryID');
    save('data/queryCAM.mat', 'queryCAM');
else
    queryID = importdata('data/queryID.mat');
    queryCAM = importdata('data/queryCAM.mat');
end

%% search the database and calcuate re-id accuracy
ap = zeros(nQuery, 1); % average precision
ap_max_rerank  = zeros(nQuery, 1); % average precision with MultiQ_max + re-ranking
ap_pairwise = zeros(nQuery, 6); % pairwise average precision with single query (see Fig. 7 in the paper)

CMC = zeros(nQuery, rank_size);
CMC_max_rerank = zeros(nQuery, rank_size);

r1 = 0; % rank 1 precision with single query
r1_max_rerank = 0; % rank 1 precision with MultiQ_max + re-ranking
r1_pairwise = zeros(nQuery, 6);% pairwise rank 1 precision with single query (see Fig. 7 in the paper)

%dist = importdata('/home/qxl/Desktop/score_distmat.mat');
dist = sqdist(Hist_test, Hist_query); % distance calculate with single query. Note that Euclidean distance is equivalent to cosine distance if vectors are l2-normalized
%dist_cos_max = (2-dist_max)./2; % cosine distance with MultiQ_max, used for re-ranking

knn = 1; % number of expanded queries. knn = 1 yields best result
%queryCam = importdata('data/queryCAM_duke.mat'); % camera ID for each query
%testCam = importdata('data/testCAM_duke.mat'); % camera ID for each database image

for k = 1:nQuery
    % load ground truth for each query (good and junk)
    good_index = intersect(find(testID == queryID(k)), find(testCAM ~= queryCAM(k)))';% images with the same ID but different camera from the query
    junk_index1 = find(testID == -1);% images neither good nor bad in terms of bbox quality
    junk_index2 = intersect(find(testID == queryID(k)), find(testCAM == queryCAM(k))); % images with the same ID and the same camera as the query
    junk_index = [junk_index1; junk_index2]';
    score = dist(:, k);
    %score_avg = dist_avg(:, k);
    %score_max = dist_max(:, k);

    % sort database images according Euclidean distance
    [~, index] = sort(score, 'ascend');  % single query

    % re-rank  select rank_size=1000 index
    index = index(1:rank_size);
    %for l=1:length(index)
    %    fprintf('%d, %s\n',index(l),test_files(index(l)).name)
    %end

    [ap(k), CMC(k, :)] = compute_AP_rerank(good_index, junk_index, index);% compute AP for single query
    %ap_pairwise(k, :) = compute_AP_multiCam(good_index, junk_index1,junk_index2, index, queryCAM(k), testCAM); % compute pairwise AP for single query
    fprintf('%d,%s::%f\n',k,query_files(k).name,ap(k));
    %%%%%%%%%%% calculate pairwise r1 precision %%%%%%%%%%%%%%%%%%%%
    %r1_pairwise(k, :) = compute_r1_multiCam(good_index, junk_index1,junk_index2, index, queryCAM(k), testCAM); % pairwise rank 1 precision with single query
    %%%%%%%%%%%%%% calculate r1 precision %%%%%%%%%%%%%%%%%%%%
end
CMC = mean(CMC);
%% print result
fprintf('single query:    mAP = %f, r1 precision = %f\r\n', mean(ap), CMC(1));
%[ap_CM, r1_CM] = draw_confusion_matrix(ap_pairwise, r1_pairwise, queryCam);
%fprintf('average of confusion matrix with single query:  mAP = %f, r1 precision = %f\r\n', (sum(ap_CM(:))-sum(diag(ap_CM)))/30, (sum(r1_CM(:))-sum(diag(r1_CM)))/30);

%% plot CMC curves
figure;
s = 50;
CMC_curve = CMC ;
plot(1:s, CMC_curve(:, 1:s));


% PLOTTOPO - plot concatenated multichannel data epochs in a topographic
% or
%              rectangular array. Uses a channel location file with the same
%              format as TOPOPLOT, or else plots data on a rectangular grid.
%              If data are all positive, they are assumed to be spectra.
% Usage:
%    >> plottopo(data, 'key1', 'val1', 'key2', 'val2')
% Or
%    >> plottopo(data,'chan_locs',frames,limits,title,channels,...
%                      axsize,colors,ydir,vert) % old function call
% Inputs:
%   data       = data consisting of consecutive epochs of (chans,frames)
%                or (chans,frames,n)
%
% Optional inputs:
%  'chanlocs'  = [struct] channel structure or file plot ERPs at channel
%                locations. See help READLOCS for data channel format.
%  'geom'      = [rows cols] plot ERP in grid (overwrite previous option).
%                Grid size for rectangular matrix. Example: [6 4].
%  'frames'    = time frames (points) per epoch {def|0 -> data length}
%  'limits'    = [xmin xmax ymin ymax]  (x's in ms or Hz) {def|0
%                 (or both y's 0) -> use data limits)
%  'ylim'      = [ymin ymax] y axis limits. Overwrite option above.
%  'title'     = [string] plot title {def|'' -> none}
%  'chans'     = vector of channel numbers to plot {def|0 -> all}
%  'axsize'    = [x y] axis size {default [.05 .08]}
%  'legend'    = [cell array] cell array of string for the legend. Note
%                the last element can be an integer to set legend
%                position.
%  'showleg'   = ['on'|'off'] show or hide legend.
%  'colors'    = [cell array] cell array of plot aspect. E.g. { 'k' 'k--' }
%                for plotting the first curve in black and the second one
%                in black dashed. Can also contain additional formatting.
%                { { 'k' 'linewidth' 2 } 'k--' } same as above but
%                the first line is bolded.
%  'ydir'      = [1|-1] y-axis polarity (pos-up = 1; neg-up = -1) {def -> -1}
%  'vert'      = [vector] of times (in ms or Hz) to plot vertical lines
%                {def none}
%  'hori'      = [vector] plot horizontal line at given ordinate values.
%  'regions'   = [cell array] cell array of size nchan. Each cell contains a
%                float array of size (2,n) each column defining a time region
%                [low high] to be highlighted.
%  'plotfunc'  = [cell] use different function for plotting data. The format
%                is { funcname arg2 arg3 arg2 ... }. arg1 is taken from the
%                data.
%
% Author: Scott Makeig and Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 3-2-98
%
% See also: PLOTDATA, TOPOPLOT

% Copyright (C) 3-2-98 from PLOTDATA Scott Makeig, 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-11-98 added channels arg -sm
% 7-15-98 added ydir arg, made pos-up the default -sm
% 7-23-98 debugged ydir arg and pos-up default -sm
% 12-22-99 added grid size option, changed to SBPLOT order -sm
% 03-16-00 added AXCOPY feature -sm & tpj
% 08-21-00 debugged axheight/axwidth setting -sm
% 01-25-02 reformated help & license, added links -ad
% 03-11-02 change the channel names plotting position and cutomize pop-up -ad
% 03-15-02 added readlocs and the use of eloc input structure -ad
% 03-15-02 debugging chanlocs structure -ad & sm

%  'chan_locs' = file of channel locations as in >> topoplot example   {grid}
%                ELSE: [rows cols] grid size for rectangular matrix. Example: [6 4]
%   frames     = time frames (points) per epoch {def|0 -> data length}
%  [limits]    = [xmin xmax ymin ymax]  (x's in ms or Hz) {def|0
%                 (or both y's 0) -> use data limits)
%  'title'     = plot title {def|0 -> none}
%   channels   = vector of channel numbers to plot & label {def|0 -> all}
%                   else, filename of ascii channel-name file
%   axsize     = [x y] axis size {default [.07 .07]}
%  'colors'    = file of color codes, 3 chars per line
%                ( '.' = space) {0 -> default color order}
%   ydir       = y-axis polarity (pos-up = 1; neg-up = -1) {def -> pos-up}
%   vert       = [vector] of times (in ms or Hz) to plot vertical lines {def none}
%   hori        = [vector] of amplitudes (in uV or dB) to plot horizontal lines {def none}
%

function plottopo(data, varargin);

%
%%%%%%%%%%%%%%%%%%%%% Graphics Settings - can be customized %%%%%%%%%%%%%%%%%%
%
LINEWIDTH     = 0.7;     % data line widths (can be non-integer)
FONTSIZE      = 10;      % font size to use for labels
CHANFONTSIZE  = 7;       % font size to use for channel names
TICKFONTSIZE  = 8;       % font size to use for axis labels
TITLEFONTSIZE = 12;      % font size to use for the plot title
PLOT_WIDTH    = 0.95;     % 0.75, width and height of plot array on figure
PLOT_HEIGHT   = 0.88;    % 0.88
gcapos = get(gca,'Position'); axis off;
PLOT_WIDTH    = gcapos(3)*PLOT_WIDTH; % width and height of gca plot array on gca
PLOT_HEIGHT   = gcapos(4)*PLOT_HEIGHT;
curfig = gcf;            % learn the current graphic figure number
%
%%%%%%%%%%%%%%%%%%%% Default settings - use commandline to override %%%%%%%%%%%
%
DEFAULT_AXWIDTH  = 0.05; %
DEFAULT_AXHEIGHT = 0.08; %
DEFAULT_SIGN = -1;                        % Default - plot positive-up
ISRECT = 0;                               % default

if nargin < 1
    help plottopo
    return
end

if length(varargin) > 0
    if length(varargin) == 1 || ~ischar(varargin{1}) || isempty(varargin{1}) || ...
        (length(varargin)>2 &  ~ischar(varargin{3}))
        options = { 'chanlocs' varargin{1} };
        if nargin > 2, options = { options{:} 'frames' varargin{2} }; end
        if nargin > 3, options = { options{:} 'limits' varargin{3} }; end
        if nargin > 5, options = { options{:} 'chans'  varargin{5} }; end
        if nargin > 6, options = { options{:} 'axsize' varargin{6} }; end
        if nargin > 7, options = { options{:} 'colors' varargin{7} }; end
        if nargin > 8, options = { options{:} 'ydir'   varargin{8} }; end
        if nargin > 9, options = { options{:} 'vert'   varargin{9} }; end
        if nargin > 10,options = { options{:} 'hori'  varargin{10} }; end
        if nargin > 4 && ~isequal(varargin{4}, 0), options = {options{:} 'title'  varargin{4} }; end
        %    , chan_locs,frames,limits,plottitle,channels,axsize,colors,ydr,vert)
    else
        options = varargin;
    end
else
    options = varargin;
end
g = finputcheck(options, { 'chanlocs'  ''    []          '';
                    'frames'    'integer'               [1 Inf]     size(data,2);
                    'chans'     { 'integer','string' }  { [1 Inf] [] }    0;
                    'geom'      'integer'               [1 Inf]     [];
                    'channames' 'string'                []          '';
                    'limits'    'float'                 []          0;
                    'ylim'      'float'                 []          [];
                    'title'     'string'                []          '';
                    'plotfunc'  'cell'                  []          {};
                    'axsize'    'float'                 [0 1]       [nan nan];
                    'regions'   'cell'                  []          {};
                    'colors'    { 'cell','string' }     []          {};
                    'legend'    'cell'                  []          {};
                    'showleg'   'string'                {'on','off'} 'on';
                    'ydir'      'integer'               [-1 1]      DEFAULT_SIGN;
                    'vert'      'float'                 []          [];
                    'hori'      'float'                 []          []});
if ischar(g), error(g); end
data = reshape(data, size(data,1), size(data,2), size(data,3));
%if length(g.chans) == 1 & g.chans(1) ~= 0, error('can not plot a single ERP'); end

[chans,framestotal]=size(data);           % data size

%
%%%%%%%%%%%%%%% Substitute defaults for missing parameters %%%%%%%%%%%%%%%%
%

axwidth  = g.axsize(1);
if length(g.axsize) < 2
    axheight = NaN;
else
    axheight = g.axsize(2);
end
if isempty(g.chans) || g.chans(1) == 0
   g.chans = 1:size(data,1);
elseif ~ischar(g.chans)
   g.chans = g.chans;
end

nolegend = 0;
if isempty(g.legend), nolegend = 1; end

if ~isempty(g.ylim)
    g.limits(3:4) = g.ylim;
end
plotgrid = 0;
if isempty(g.chanlocs) % plot in a rectangular grid
    plotgrid = 1;
elseif ~isfield(g.chanlocs, 'theta')
    plotgrid = 1;
end
if length(g.chans) < 4 && ~plotgrid
    disp('Not enough channels, does not use channel coordinate to plot axis');
    plotgrid = 1;
end
if plotgrid && isempty(g.geom)
  n = ceil(sqrt(length(g.chans)));
  g.geom = [n ceil(length(g.chans)/n)];
end
if ~isempty(g.geom)
    plotgrid = 1;
end
%
%%%%%%%%%%%%%%%%%%%%%%%%%%% Test parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  icadefs; % read BACKCOLOR, MAXPLOTDATACHANS constant from icadefs.m
  if g.frames <=0,
    g.frames = framestotal;    % default
    datasets=1;
  elseif g.frames==1,
    fprintf('plottopo: cannot plot less than 2 frames per trace.\n');
    return
    datasets=1;
  else
    datasets = fix(framestotal/g.frames);        % number of traces to overplot
  end

  if max(g.chans) > chans
    fprintf('plottopo(): max channel index > %d channels in data.\n',...
                       chans);
    return
  end
  if min(g.chans) < 1
    fprintf('plottopo(): min channel index (%g) < 1.\n',...
                       min(g.chans));
    return
  end
  if length(g.chans)>MAXPLOTDATACHANS,
    fprintf('plottopo(): not set up to plot more than %d traces.\n',...
                       MAXPLOTDATACHANS);
    return
  end

  if datasets>MAXPLOTDATAEPOCHS
      fprintf('plottopo: not set up to plot more than %d epochs.\n',...
                       MAXPLOTDATAEPOCHS);
    return
  end
  if datasets<1
      fprintf('plottopo: cannot plot less than 1 epoch!\n');
      return
  end

  if ~isempty(g.geom)
      if isnan(axheight) % if not specified
          axheight = gcapos(4)/(g.geom(1)+1);
          axwidth  = gcapos(3)/(g.geom(2)+1);
      end
      % if chan_locs(2) > 5
      %     axwidth = 0.66/(chan_locs(2)+1);
      % end
  elseif isnan(axwidth)
      axheight = DEFAULT_AXHEIGHT;
      axwidth =  DEFAULT_AXWIDTH;
  end
    fprintf('Plotting data using axis size [%g,%g]\n',axwidth,axheight);

    %
    %%%%%%%%%%%%% Extend the size of the plotting area in the window %%%%%%%%%%%%
    %
    curfig = gcf;
    h=figure(curfig);
    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');

    set(gca,'Color',BACKCOLOR);               % set the background color

    axcolor= get(0,'DefaultAxesXcolor'); % find what the default x-axis color is
    vertcolor = 'k';
    horicolor = vertcolor;

%     %
%     %%%%%%%%%%%%%%%%%%%% Read the channel names %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     %
%     if isempty(g.channames)
%         if ~ischar(g.chans)
%             % g.channames = zeros(MAXPLOTDATACHANS,4);
%             % for c=1:length(g.chans),
%             %     g.channames(c,:)= sprintf('%4d',g.chans(c));
%             % end
%             if length(g.chans) > 1 | g.chans(1) ~= 0
%                 g.channames = num2str(g.chans(:));                   %%CJH
%             end
%         else % ischar(g.chans)
%             chid = fopen(g.chans,'r');
%             if chid <3,
%                 fprintf('PLOTTOPO: cannot open file %s.\n',g.chans);
%                 return
%             else
%                 fprintf('PLOTTOPO: opened file %s.\n',g.chans);
%             end
%
%             %%%%%%%
%             % fid=fopen('fgetl.m');
%             % while 1
%             %   line = fgetl(fid);
%             %   if ~ischar(line), break, end
%             %     disp(line)
%             %   end
%             % end
%             % fclose(fid);
%             %%%%%%%
%
%             g.channames = fscanf(chid,'%s',[4 MAXPLOTDATACHANS]);
%             g.channames = g.channames';
%             [r c] = size(g.channames);
%             for i=1:r
%                 for j=1:c
%                     if g.channames(i,j)=='.',
%                         g.channames(i,j)=' ';
%                     end
%                 end
%             end
%         end; % setting g.channames
%     end
%
    %
    %%%%%%%%%%%%%%%%%%%%%%%%% Plot and label specified channels %%%%%%%%%%%%%%%%%%
    %
    data = data(g.chans,:);
    chans = length(g.chans);

    %
    %%%%%%%%%%%%%%%%%%%%%%%%% Read the color names %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    if ischar(g.colors) % filename for backward compatibility but not documented
        cid = fopen(g.colors,'r');
        % fprintf('cid = %d\n',cid);
        if cid <3,
            fprintf('plottopo: cannot open file %s.\n',g.colors);
            return
        end
        g.colors = fscanf(cid,'%s',[3 MAXPLOTDATAEPOCHS]);
        g.colors = g.colors';
        [r c] = size(g.colors);
        for i=1:r
            for j=1:c
                if g.colors(i,j)=='.',
                    g.colors(i,j)=' ';
                end
            end
        end
        g.colors = cellstr(g.colors);
        for c=1:length(g.colors)   % make white traces black unless axis color is white
            if g.colors{c}(1)=='w' && axcolor~=[1 1 1]
                g.colors{c}(1)='k';
            end
        end
    else % use default color order (no yellow!)
        tmpcolors = { 'b' 'r' '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'};
        g.colors = {g.colors{:} tmpcolors{:}};  % make > 64 available
    end
    %
    %%%%%%%%%%%%%%%%%%%%%%% Read and adjust limits %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    if g.limits==0,      % == 0 or [0 0 0 0]
        xmin=0;
        xmax=g.frames-1;
        % for abs max scaling:
        ymax=max(max(abs(data)));
        ymin=ymax*-1;
        % for data limits:
        %ymin=min(min(data));
        %ymax=max(max(data));
    else
        if length(g.limits)~=4,
            error('plottopo: limits should be 0 or an array [xmin xmax ymin ymax].\n');
        end
        xmin = g.limits(1);
        xmax = g.limits(2);
        ymin = g.limits(3);
        ymax = g.limits(4);
    end

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

    if ymax == 0 && ymin == 0,
        % for abs max scaling:
        ymax=max(max(abs(data)));
        ymin=ymax*-1;
        % for data limits:
        %ymin=min(min(data));
        %ymax=max(max(data));
    end
    if ymax<=ymin,
        fprintf('plottopo() - ymax must be > ymin.\n')
        return
    end

    xlabel = 'Time (ms)';
    %
    %%%%%%%%%%%%%%%%%%%%%% 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) subplot 1
    figure(curfig); h=gca;title(g.title,'FontSize',TITLEFONTSIZE); % title plot
    hold on
    msg = ['Plotting %d traces of %d frames with colors: '];

    for c=1:datasets
        cind = mod(c-1, length(g.colors))+1;
        if iscell(g.colors{cind})
            msg = [msg  '''' g.colors{cind}{1} ''' ' ];
        else
            msg = [msg  '''' g.colors{cind} ''' ' ];
        end
    end
    msg = [msg '\n'];    % print starting info on screen . . .
    fprintf('limits: [xmin,xmax,ymin,ymax] = [%4.1f %4.1f %4.2f %4.2f]\n',...
            xmin,xmax,ymin,ymax);
    fprintf(msg,datasets,g.frames);

    set(h,'FontSize',FONTSIZE);           % choose font size
    set(h,'YLim',[ymin ymax]);            % set default plotting parameters
    set(h,'XLim',[xmin xmax]);

    axis('off')
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%% Read chan_locs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    if plotgrid
        ISRECT = 1;
        ht = g.geom(1);
        wd = g.geom(2);
        if chans > ht*wd
            fprintf('plottopo(): (%d) channels to be plotted > grid size [%d %d]\n',...
                    chans,ht,wd);
            return
        end
        xvals = 0; yvals = 0;
        if isempty(g.channames)
            if isfield(g.chanlocs,'labels') && ~iscellstr({g.chanlocs.labels})
                g.channames = strvcat(g.chanlocs.labels);
            else
                g.channames = repmat(' ',ht*wd,4);
                for i=1:ht*wd
                    channum = num2str(i);
                    g.channames(i,1:length(channum)) = channum;
                end
            end
        end

    else % read chan_locs file
         % read the channel location file
         % ------------------------------
        if isstruct(g.chanlocs)
            nonemptychans = cellfun('isempty', { g.chanlocs.theta });
            nonemptychans = find(~nonemptychans);
            [tmp g.channames Th Rd] = readlocs(g.chanlocs(nonemptychans));
            g.channames = strvcat({ g.chanlocs.labels });
        else
            [tmp g.channames Th Rd] = readlocs(g.chanlocs);
            g.channames = strvcat(g.channames);
            nonemptychans = [1:length(g.channames)];
        end
        Th = pi/180*Th;                 % convert degrees to radians
        Rd = Rd;

        if length(g.chans) > length(g.chanlocs),
            error('plottopo(): data channels must be <= ''chanlocs'' channels')
        end

        [yvalstmp,xvalstmp] = pol2cart(Th,Rd); % translate from polar to cart. coordinates
        xvals(nonemptychans) = xvalstmp;
        yvals(nonemptychans) = yvalstmp;

        % find position for other channels
        % --------------------------------
        totalchans = length(g.chanlocs);
        emptychans = setdiff_bc(1:totalchans, nonemptychans);
        totalchans = floor(sqrt(totalchans))+1;
        for index = 1:length(emptychans)
            xvals(emptychans(index)) = 0.7+0.2*floor((index-1)/totalchans);
            yvals(emptychans(index)) = -0.4+mod(index-1,totalchans)/totalchans;
        end
        g.channames = g.channames(g.chans,:);
        xvals     = xvals(g.chans);
        yvals     = yvals(g.chans);
    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % xvals = 0.5+PLOT_WIDTH*xvals;   % controls width of  plot array on page!
    % yvals = 0.5+PLOT_HEIGHT*yvals;  % controls height of plot array on page!
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if length(xvals) > 1
        if length(unique(xvals)) > 1
            xvals = (xvals-mean([max(xvals) min(xvals)]))/(max(xvals)-min(xvals)); % recenter
            xvals = gcapos(1)+gcapos(3)/2+PLOT_WIDTH*xvals;   % controls width of plot
                                                              % array on current axes
        end
    end
    yvals = gcapos(2)+gcapos(4)/2+PLOT_HEIGHT*yvals;  % controls height of plot
                                                      % array on current axes
                                                      %
                                                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Plot traces %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                                      %

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

    Axes = [];
    for P=0:datasets-1, %  for each data epoch
        fprintf('trace %d: ',P+1);

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

            if P>0 % subsequent pages (Axes specified)
                axes(Axes(c))
                hold on;                      % plot down left side of page first
                axis('off')
            else   % first page, specify axes
                if plotgrid
                    Axes = [ Axes sbplot(g.geom(1), g.geom(2), c)];
                else
                    xcenter = xvals(c);
                    ycenter = yvals(c);
                    Axes = [Axes axes('Units','Normal','Position', ...
                                      [xcenter-axwidth/2 ycenter-axheight/2 axwidth axheight])];
                end
                %axes(Axes(c))
                axis('off')

                hold on;                      % plot down left side of page first
                                              % set(h,'YLim',[ymin ymax]);    % set default plotting parameters
                                              % set(h,'XLim',[xmin xmax]);

                axislcolor = get(gca,'Xcolor');   %%CJH

                axis('off');

                % secondx = 200;                             % draw second vert axis
                % axis('off');plot([secondx secondx],[ymin ymax],'color',axislcolor);
                %
                %%%%%%%%%%%%%%%%%%%%%%% Print channel names %%%%%%%%%%%%%%%%%%%%%%%%%%
                %
                NAME_OFFSET = -.25;
                NAME_OFFSETY = .2;
                if ymin <= 0 && ymax >= 0,
                    yht = 0;
                else
                    yht = mean(data(c,1+P*g.frames:1+P*g.frames+g.frames-1));
                end
                if ~ISRECT    % print before traces
                    xt = double(xmin-NAME_OFFSET*xdiff);
                    yt = double(yht-NAME_OFFSETY*ydiff);
                    str = [g.channames(c,:)];
                    h=text(xt,yt,str);
                    set(h,'HorizontalAlignment','right');
                    %set(h,'FontSize',CHANFONTSIZE);           % choose font size
                else % ISRECT
                    xmn = xdiff/2+xmin;
                    h=text(double(xmn),double(ymax+0.05*ymax),[g.channames(c,:)]);
                    set(h,'HorizontalAlignment','right');
                    %set(h,'FontSize',CHANFONTSIZE);            % choose font size
                end % ISRECT

                %
                %%%%%%%%%%%%%%%%%%%%%%% Highlight regions %%%%%%%%%%%%%%%%%%%%%%%%%%
                %
                if ~isempty(g.regions)
                    for index=1:size(g.regions{c},2)
                        tmpreg = g.regions{c}(:,index);
                        if tmpreg(1) ~= tmpreg(2)
                            tmph = patch([tmpreg(1) tmpreg(2) tmpreg(2) tmpreg(1)], ...
                                         [-100 -100 100 100], [0.9 0.9 0.9]); hold on;
                            set(tmph, 'edgecolor', [0.9 0.9 0.9]); %,'facealpha',0.5,'edgealpha',0.5);
                        end
                    end
                end

            end; % P=0

            %
            %%%%%%%%%%%%%%%%%%%%%%% Plot data traces %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            %
            Pind = mod(P+1-1, length(g.colors))+1;
            if ~iscell( g.colors{Pind} ), tmpcolor = { g.colors{Pind} 'linewidth' LINEWIDTH };
            else                          tmpcolor = g.colors{Pind};
            end
            ymn = min([ymax ymin]);
            ymx = max([ymax ymin]);
            if isempty(g.plotfunc)
                if ischar(tmpcolor{1}) && length(tmpcolor) > 1
                    plot(x,data(c,1+P*g.frames:1+P*g.frames+g.frames-1), tmpcolor{1}, tmpcolor{2:end});
                else
                    plot(x,data(c,1+P*g.frames:1+P*g.frames+g.frames-1), 'color', tmpcolor{:});
                end;
                if g.ydir == -1
                    set(gca, 'ydir', 'reverse');
                end
                axis([xmin xmax ymn ymx]);          % set axis bounds
            elseif P == 1
                func = eval( [ '@' g.plotfunc{1} ] );
                feval(func, data(c,:), g.plotfunc{2:end});
            end

            if P == datasets-1 % last pass
                               %
                               %%%%%%%%%%%%%%%%%%%%%%% Plot lines %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                               %
                plot([0 0],[ymin ymax],'color',axislcolor); % draw vert axis at time 0
                axis('off');
                plot([xmin xmax],[0 0],'color',axislcolor);  % draw horizontal axis

                %
                %%%%%%%%%%%%%%%%%%%% plot vertical lines (optional) %%%%%%%%%%%%%%%%%
                %

                if isempty(g.vert)
                    g.vert = [xmin xmax];
                    ymean = (ymin+ymax)/2;
                    vmin = ymean-0.1*(ymean-ymin);
                    vmax = vmin*-1;  %ymean+0.2*(ymax-ymean);
                elseif ~isnan(g.vert)
                    ymean = (ymin+ymax)/2;
                    vmin = ymean-0.1*(ymean-ymin);
                    vmax = vmin*-1;  %ymean+0.2*(ymax-ymean);
                    for v = g.vert
                        plot([v v],[vmin vmax],'color',vertcolor); % draw vertical lines
                    end
                end

                %
                %%%%%%%%%%%%%%%%%%%% plot horizontal lines (optional) %%%%%%%%%%%%%%%
                %
                if isempty(g.hori)
                    g.hori = [ymin ymax];
                end
                if ~isnan(g.hori)
                    xmean = 0;
                    hmin = xmean-0.2*(xmean-xmin);
                    hmax = hmin*-1; %xmean+0.3*(xmax-xmean);
                    for v = g.hori
                        plot([hmin hmax],[v v], 'color',horicolor); % draw horizontal lines
                    end
                end

            end

            fprintf(' %d',c); % finished with channel plot
        end; % c, chans / subplot
             % handle legend
        if nolegend, g.legend{P+1} = ['Data ' int2str(P) ]; end

        fprintf('\n');
    end; % P / epoch

    %
    %%%%%%%%%%%%%%%%%%%%% Make time and amp cal bar %%%%%%%%%%%%%%%%%%%%%%%%%
    %
    ax = axes('Units','Normal','Position', ...
              [0.85 0.1 axwidth axheight]); % FIX!!!!
    axes(ax)
    axis('off');
    if xmin <=0
        figure(curfig);p=plot([0 0],[ymn ymx],'color','k'); % draw vert axis at zero
    else
        figure(curfig);p=plot([xmin xmin],[ymn ymx],'color','k'); % draw vert axis at zero
    end
    if g.ydir == -1
        set(gca, 'ydir', 'reverse');
    end
    axis([xmin xmax ymn ymx]);        % set axis values
    hold on
    %set(p, 'Clipping','off');        % center text
    figure(curfig);p=plot([xmin xmax],[0 0],'color',axislcolor); % draw horizontal axis
    axis([xmin xmax ymin ymax]);        % set axis values
                                        %
                                        %%%%%%%%%%%%%%%%%%%% plot vertical lines (optional) %%%%%%%%%%%%%%%%%
                                        %
    if ~isnan(g.vert)
        for v = g.vert
            figure(curfig);plot([v v],[vmin vmax],'color',vertcolor); % draw vertical lines
        end
    end
    %
    %%%%%%%%%%%%%%%%%%%% plot horizontal lines (optional) %%%%%%%%%%%%%%%%%
    %
    if ~isnan(g.hori)
        xmean = 0;
        hmin = xmean-0.2*(xmean-xmin);
        hmax = hmin*-1; %xmean+0.3*(xmax-xmean);
        for v = g.hori
            figure(curfig);plot([hmin hmax],[v v], 'color',horicolor); % draw horizontal lines
        end
    end

    % secondx = 200;                    % draw second vert axis
    % axis('off');plot([secondx secondx],[ylo ymax],'color',axislcolor);
    %
    %%%%%%%%%%%%%%%%%%%%% Plot negative-up %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    signx = xmin-0.15*xdiff;
    figure(curfig);axis('off');h=text(double(signx),double(ymin),num2str(ymin,3)); % text ymin
    set(h,'FontSize',TICKFONTSIZE);               % choose font size
    set(h,'HorizontalAlignment','right','Clipping','off');

    figure(curfig);axis('off');h=text(double(signx), double(ymax),['+' num2str(ymax,3)]);  % text +ymax
    set(h,'FontSize',TICKFONTSIZE);         % choose font size
    set(h,'HorizontalAlignment','right','Clipping','off');

    ytick = g.ydir*(-ymax-0.3*ydiff);
    figure(curfig);tick = [int2str(xmin)]; h=text(double(xmin),double(ytick),tick);
    set(h,'FontSize',TICKFONTSIZE);         % choose font size
    set(h,'HorizontalAlignment','center',...
          'Clipping','off');  % center text

    tick = [xlabel]; figure(curfig);h=text(double(xmin+xdiff/2),double(ytick-0.5*g.ydir*ydiff),tick);
    set(h,'FontSize',TICKFONTSIZE);         % choose font size
    set(h,'HorizontalAlignment','center',...
          'Clipping','off');  % center text

    tick = [int2str(xmax)]; figure(curfig);h=text(double(xmax),double(ytick),tick);
    set(h,'FontSize',TICKFONTSIZE);         % choose font size
    set(h,'HorizontalAlignment','center',...
          'Clipping','off');  % center text

    if length(g.legend) > 1 && strcmpi(g.showleg, 'on')
        tmpleg = vararg2str(g.legend);
        quotes = find(tmpleg == '''');
        for index = length(quotes):-1:1
            tmpleg(quotes(index)+1:end+1) = tmpleg(quotes(index):end);
            tmpleg(quotes(index)) = '''';
        end
        tmpleg = [ 'legend(' tmpleg ');' ];
    else tmpleg = '';
    end
    com = [ 'axis on;' ...
            'clear xlabel ylabel;' tmpleg ...
            'xlabel(''''Time (ms)'''');' ...
            'ylabel(''''Potential (\muV)'''');' ];
    axcopy(gcf, com); % turn on popup feature
                      %
                      %%%%%%%%%%%%%%%%%% Make printed figure fill page %%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %
    orient tall
    % curfig = gcf;
    % h=figure(curfig);
    % set(h,'PaperPosition',[0.2 0.3 7.6 10]); % stretch out the plot on the page