% WRITELOCS - write a file containing channel location, type and gain information
%             
% Usage:
%   >> writelocs( chanstruct, filename );
%   >> writelocs( chanstruct, filename, 'key', 'val' );
%
% Inputs:
%   chanstruct - EEG.chanlocs data structure returned by READLOCS containing
%                channel location, type and gain information.
%   filename   - File name for saving channel location, type and gain information
%
% Optional inputs:
%   'filetype'  - ['loc'|'sph'|'sfp'|'xyz'|'polhemus'|'besa'|'chanedit'|'custom'] 
%                 Type of the file to write. By default the file type is indicated 
%                 by the file extension. 
%                  'loc' - An EEGLAB 2-D polar coordinates channel locations file 
%                          Coordinates are theta and radius (see definitions below).
%                  'sph' - A Matlab spherical coordinates file (Note: spherical
%                          coordinates used by Matlab functions are different 
%                          from spherical coordinates used in BESA - see below).
%                  'sfp' - EGI cartesian coordinates (not Matlab cartesian - see below).
%                  'xyz' - MATLAB/EEGLAB cartesian coordinates (Not EGI cartesian; 
%                          z is toward nose; y is toward left ear; z is toward vertex).
%                  'polhemus' or 'polhemusx' - Polhemus electrode location file recorded with 
%                          'X' on sensor pointing to subject (see below and READELP).
%                  'polhemusy' - Polhemus electrode location file recorded with 
%                          'Y' on sensor pointing to subject (see below and READELP).
%                  'besa' - BESA'(.elp') spherical coordinate file. (Not MATLAB spherical
%                           - see below).
%                  'chanedit' - EEGLAB channel location files created by POP_CHANEDIT.
%                  'custom' - Ascii files with columns in user-defined 'format' (see below).
%   'format'    - [cell array] Format of a 'custom' channel location file (see above).
%                          Default if no file type is defined. The cell array contains
%                          labels defining the meaning of each column of the input file.
%                           'channum'   [positive integer] channel number 
%                           'labels'    [string] channel name (no spaces)
%                           'theta'     [real degrees] 2-D angle in polar coordinates. 
%                                       positive => rotating from nose (0) toward left ear 
%                           'radius'    [real] radius in 2-D polar coords (0.5 is disk limits)
%                           'X'         [real] Matlab-cartesian X coordinate (to nose)
%                           'Y'         [real] Matlab-cartesian Y coordinate (to left ear)
%                           'Z'         [real] Matlab-cartesian Z coordinate (to vertex)
%                           '-X','-Y','-Z' Matlab-cartesian coordinates pointing away from above
%                           'sph_theta' [real degrees] Matlab spherical horizontal angle. 
%                                       positive => rotating from nose (0) toward left ear.
%                           'sph_phi'   [real degrees] Matlab spherical elevation angle;
%                                       positive => rotating from horizontal (0) upwards.
%                           'sph_radius' [real] distance from head center (unused) 
%                           'sph_phi_besa' [real degrees] BESA phi angle from vertical. 
%                                       positive => rotating from vertex (0) towards right ear.
%                           'sph_theta_besa' [real degrees] BESA theta horiz/azimuthal angle. 
%                                       positive => rotating from right ear (0) toward nose.
%     The input file may also contain other channel information fields
%                           'type'      channel type: 'EEG', 'MEG', 'EMG', 'ECG', others ...
%                           'calib'     [real near 1.0] channel calibration value.
%                           'gain'      [real > 1] channel gain. 
%                           'custom1'   custom field #1.
%                           'custom2', 'custom3', 'custom4' more custom fields.
%   'unicoord'     - ['on'|'off'] Uniformize all coordinates. Default 'on'.
%   'header'       - ['on'|'off'] Add a header comment line with the name of each column.
%                             Comment lines begin with '%'. Default is 'off'.
%   'customheader' - [string] Add a custom header at the beginning of the file and
%                             preceded by '%'.  If used with 'header' set to 'on', 
%                             the column names will be inserted after the custom header.
%   'elecind' - [integer array] Indices of channels to export. 
%                             Default is all channels.
%
% Note: for file formats, see READLOCS help  (>> help readlocs)
%
% Author: Arnaud Delorme, Salk Institute, 16 Dec 2002
%
% See also: READLOCS, READELP

% Copyright (C) Arnaud Delorme, CNL / Salk Institute, 28 Feb 2002
%
% 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.

function writelocs( chans, filename, varargin ); 

if nargin < 2
	help writelocs;
	return;
end

% get infos from readlocs
% -----------------------
%[listtype formatinfo listcolformat formatskip] = readlocs('getinfos');
[chanformat listcolformat] = readlocs('getinfos');
indformat  = [];
for index = 1:length(chanformat), 
    if ~ischar(chanformat(index).importformat)
        indformat = [ indformat index ];
    end
    if isempty(chanformat(index).skipline), chanformat(index).skipline = 0; end
end
listtype   = { chanformat(indformat).type };
formatinfo = { chanformat(indformat).importformat };
formatskip = [ chanformat(indformat).skipline ];

g = finputcheck( varargin, ...
                 { 'filetype'	  'string'	 listtype 			'loc';
                   'header'       'string'   { 'on','off' } 	'off';
                   'customheader' 'string'   [] 					'';
                   'elecind'      'integer'  [1 Inf]				[];
                   'unicoord'     'string'   { 'on','off' } 	'on'; 
                   'format'		  'cell'	 []					{} }, 'writelocs');
if ischar(g), error(g); end;  

if strcmpi(g.unicoord, 'on')
    disp('Uniformizing coordinates');
    chans = convertlocs(chans, 'auto', 'verbose', 'off');
end

% select channels
% ---------------
if ~isempty(g.elecind)
	chans = chans(g.elecind);
end

% finding types of input
% ----------------------
if isempty(g.format)
   indexformat = strmatch(lower(g.filetype), listtype, 'exact');
   g.format = formatinfo{indexformat};
   g.skipline = formatskip(indexformat);
else 
   g.skipline = 0;   
end

% creating file
% -------------
fid = fopen(filename, 'w');

% exporting header
% ----------------
if ~isempty(g.customheader)
    allstrs = cellstr(g.customheader);
    for index=1:length(allstrs)
        fprintf(fid, '%s\n', allstrs{index});
    end
end
if  strcmpi(g.header, 'on') || g.skipline == 2
   for index=1:length(g.format)
      fprintf(fid, '%8s\t', g.format{index});
   end
   fprintf(fid, '\n');
   for index=1:length(g.format)
      fprintf(fid, '%8s\t', char(ones(1,8)*45));
   end
   fprintf(fid, '\n');
end
if g.skipline == 1
   fprintf(fid, '%d\n', length(chans));
end;         

% writing infos
% -------------
for indexchan = 1:length(chans)
   for index=1:length(g.format)
      [str, mult] = checkformat(g.format{index});
      if strcmpi(str, 'channum')
         fprintf(fid, '%d', indexchan);
      else
         if ~isfield(chans, str)
            error([ 'Non-existant field: ''' str '''' ]);
         end
         eval( [ 'chanval = chans(indexchan).' str ';' ] );
         if   ischar(chanval), fprintf(fid, '%8s', chanval);
         else   	
             if abs(mult*chanval) > 1E-10
                 fprintf(fid, '%8s', num2str(mult*chanval,5));
             else
                 fprintf(fid, '%8s', '0');
             end
         end
      end
      if index ~= length(g.format)
         fprintf(fid, '\t');
      end;         
   end
   fprintf(fid, '\n');
end
fclose(fid);

return;

% check field format
% ------------------
function [str, mult] = checkformat(str)
	mult = 1;
	if strcmpi(str, 'labels'), str = lower(str); return; end
	if strcmpi(str, 'channum'), str = lower(str); return; end
	if strcmpi(str, 'theta'), str = lower(str); return; end
	if strcmpi(str, 'radius'), str = lower(str); return; end
	if strcmpi(str, 'sph_theta'), str = lower(str); return; end
	if strcmpi(str, 'sph_phi'), str = lower(str); return; end
	if strcmpi(str, 'sph_radius'), str = lower(str); return; end
	if strcmpi(str, 'sph_theta_besa'), str = lower(str); return; end
	if strcmpi(str, 'sph_phi_besa'), str = lower(str); return; end
	if strcmpi(str, 'gain'), str = lower(str); return; end
	if strcmpi(str, 'calib'), str = lower(str); return; end
	if strcmpi(str, 'type') , str = lower(str); return; end
	if strcmpi(str, 'X'), str = upper(str); return; end
	if strcmpi(str, 'Y'), str = upper(str); return; end
	if strcmpi(str, 'Z'), str = upper(str); return; end
	if strcmpi(str, '-X'), str = upper(str(2:end)); mult = -1; return; end
	if strcmpi(str, '-Y'), str = upper(str(2:end)); mult = -1; return; end
	if strcmpi(str, '-Z'), str = upper(str(2:end)); mult = -1; return; end
	if strcmpi(str, 'custum1'), return; end
	if strcmpi(str, 'custum2'), return; end
	if strcmpi(str, 'custum3'), return; end
	if strcmpi(str, 'custum4'), return; end
   error(['writelocs: undefined field ''' str '''']);
   
