123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- % readlocs() - read electrode location coordinates and other information from a file.
- % Several standard file formats are supported. Users may also specify
- % a custom column format. Defined format examples are given below
- % (see File Formats).
- % Usage:
- % >> eloc = readlocs( filename );
- % >> EEG.chanlocs = readlocs( filename, 'key', 'val', ... );
- % >> [eloc, labels, theta, radius, indices] = ...
- % readlocs( filename, 'key', 'val', ... );
- % Inputs:
- % filename - Name of the file containing the electrode locations
- % {default: 2-D polar coordinates} (see >> help topoplot )
- %
- % Optional inputs:
- % 'filetype' - ['loc'|'sph'|'sfp'|'xyz'|'asc'|'polhemus'|'besa'|'chanedit'|'custom']
- % Type of the file to read. By default the file type is determined
- % using the file extension (see below under File Formats),
- % 'loc' an EEGLAB 2-D polar coordinates channel locations file
- % Coordinates are theta and radius (see definitions below).
- % 'sph' Matlab spherical coordinates (Note: spherical
- % coordinates used by Matlab functions are different
- % from spherical coordinates used by 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
- % 'asc' Neuroscan polar coordinates.
- % '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 coordinates. (Not MATLAB spherical -
- % see below).
- % 'chanedit' - EEGLAB channel location file created by pop_chanedit().
- % 'custom' - Ascii file with columns in user-defined 'format' (see below).
- % 'importmode' - ['eeglab'|'native'] for location files containing 3-D cartesian electrode
- % coordinates, import either in EEGLAB format (nose pointing toward +X).
- % This may not always be possible since EEGLAB might not be able to
- % determine the nose direction for scanned electrode files. 'native' import
- % original carthesian coordinates (user can then specify the position of
- % the nose when calling the topoplot() function; in EEGLAB the position
- % of the nose is stored in the EEG.chaninfo structure). {default 'eeglab'}
- % '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 for 2-D polar coords; 0.5 is the head
- % disk radius and limit for topoplot() plotting).
- % '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 opposite
- % to the 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.
- % 'ignore' ignore column}.
- % 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', etc. more custom fields
- % 'skiplines' - [integer] Number of header lines to skip (in 'custom' file types only).
- % Note: Characters on a line following '%' will be treated as comments.
- % 'readchans' - [integer array] indices of electrodes to read. {default: all}
- % 'center' - [(1,3) real array or 'auto'] center of xyz coordinates for conversion
- % to spherical or polar, Specify the center of the sphere here, or 'auto'.
- % This uses the center of the sphere that best fits all the electrode
- % locations read. {default: [0 0 0]}
- % Outputs:
- % eloc - structure containing the channel names and locations (if present).
- % It has three fields: 'eloc.labels', 'eloc.theta' and 'eloc.radius'
- % identical in meaning to the EEGLAB struct 'EEG.chanlocs'.
- % labels - cell array of strings giving the names of the electrodes. NOTE: Unlike the
- % three outputs below, includes labels of channels *without* location info.
- % theta - vector (in degrees) of polar angles of the electrode locations.
- % radius - vector of polar-coordinate radii (arc_lengths) of the electrode locations
- % indices - indices, k, of channels with non-empty 'locs(k).theta' coordinate
- %
- % File formats:
- % If 'filetype' is unspecified, the file extension determines its type.
- %
- % '.loc' or '.locs' or '.eloc':
- % polar coordinates. Notes: angles in degrees:
- % right ear is 90; left ear -90; head disk radius is 0.5.
- % Fields: N angle radius label
- % Sample: 1 -18 .511 Fp1
- % 2 18 .511 Fp2
- % 3 -90 .256 C3
- % 4 90 .256 C4
- % ...
- % Note: In previous releases, channel labels had to contain exactly
- % four characters (spaces replaced by '.'). This format still works,
- % though dots are no longer required.
- % '.sph':
- % Matlab spherical coordinates. Notes: theta is the azimuthal/horizontal angle
- % in deg.: 0 is toward nose, 90 rotated to left ear. Following this, performs
- % the elevation (phi). Angles in degrees.
- % Fields: N theta phi label
- % Sample: 1 18 -2 Fp1
- % 2 -18 -2 Fp2
- % 3 90 44 C3
- % 4 -90 44 C4
- % ...
- % '.elc':
- % Cartesian 3-D electrode coordinates scanned using the EETrak software.
- % See readeetraklocs().
- % '.elp':
- % Polhemus-.'elp' Cartesian coordinates. By default, an .elp extension is read
- % as PolhemusX-elp in which 'X' on the Polhemus sensor is pointed toward the
- % subject. Polhemus files are not in columnar format (see readelp()).
- % '.elp':
- % BESA-'.elp' spherical coordinates: Need to specify 'filetype','besa'.
- % The elevation angle (phi) is measured from the vertical axis. Positive
- % rotation is toward right ear. Next, perform azimuthal/horizontal rotation
- % (theta): 0 is toward right ear; 90 is toward nose, -90 toward occiput.
- % Angles are in degrees. If labels are absent or weights are given in
- % a last column, readlocs() adjusts for this. Default labels are E1, E2, ...
- % Fields: label phi theta
- % Sample: Fp1 -92 -72
- % Fp2 92 72
- % C3 -46 0
- % C4 46 0
- % ...
- % '.xyz':
- % Matlab/EEGLAB Cartesian coordinates. Here. x is towards the nose,
- % y is towards the left ear, and z towards the vertex. Note that the first
- % column (x) is -Y in a Matlab 3-D plot, the second column (y) is X in a
- % matlab 3-D plot, and the third column (z) is Z.
- % Fields: channum x y z label
- % Sample: 1 .950 .308 -.035 Fp1
- % 2 .950 -.308 -.035 Fp2
- % 3 0 .719 .695 C3
- % 4 0 -.719 .695 C4
- % ...
- % '.asc', '.dat':
- % Neuroscan-.'asc' or '.dat' Cartesian polar coordinates text file.
- % '.sfp':
- % BESA/EGI-xyz Cartesian coordinates. Notes: For EGI, x is toward right ear,
- % y is toward the nose, z is toward the vertex. EEGLAB converts EGI
- % Cartesian coordinates to Matlab/EEGLAB xyz coordinates.
- % Fields: label x y z
- % Sample: Fp1 -.308 .950 -.035
- % Fp2 .308 .950 -.035
- % C3 -.719 0 .695
- % C4 .719 0 .695
- % ...
- % '.ced':
- % ASCII file saved by pop_chanedit(). Contains multiple MATLAB/EEGLAB formats.
- % Cartesian coordinates are as in the 'xyz' format (above).
- % Fields: channum label theta radius x y z sph_theta sph_phi ...
- % Sample: 1 Fp1 -18 .511 .950 .308 -.035 18 -2 ...
- % 2 Fp2 18 .511 .950 -.308 -.035 -18 -2 ...
- % 3 C3 -90 .256 0 .719 .695 90 44 ...
- % 4 C4 90 .256 0 -.719 .695 -90 44 ...
- % ...
- % The last columns of the file may contain any other defined fields (gain,
- % calib, type, custom).
- %
- % Author: Arnaud Delorme, Salk Institute, 8 Dec 2002 (expanded from the previous EEG/ICA
- % toolbox function)
- %
- % See also: readelp(), writelocs(), topo2sph(), sph2topo(), sph2cart()
- % Copyright (C) Arnaud Delorme, CNL / Salk Institute, 28 Feb 2002
- %
- % 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
- function [eloc, labels, theta, radius, indices] = cm_eeg_readlocs_20140226( filename, varargin );
- if nargin < 1
- help readlocs;
- return;
- end;
- % NOTE: To add a new channel format:
- % ----------------------------------
- % 1) Add a new element to the structure 'chanformat' (see 'ADD NEW FORMATS HERE' below):
- % 2) Enter a format 'type' for the new file format,
- % 3) Enter a (short) 'typestring' description of the format
- % 4) Enter a longer format 'description' (possibly multiline, see ex. (1) below)
- % 5) Enter format file column labels in the 'importformat' field (see ex. (2) below)
- % 6) Enter the number of header lines to skip (if any) in the 'skipline' field
- % 7) Document the new channel format in the help message above.
- % 8) After testing, please send the new version of readloca.m to us
- % at eeglab@sccn.ucsd.edu with a sample locs file.
- % The 'chanformat' structure is also used (automatically) by the writelocs()
- % and pop_readlocs() functions. You do not need to edit these functions.
- chanformat(1).type = 'polhemus';
- chanformat(1).typestring = 'Polhemus native .elp file';
- chanformat(1).description = [ 'Polhemus native coordinate file containing scanned electrode positions. ' ...
- 'User must select the direction ' ...
- 'for the nose after importing the data file.' ];
- chanformat(1).importformat = 'readelp() function';
- % ---------------------------------------------------------------------------------------------------
- chanformat(2).type = 'besa';
- chanformat(2).typestring = 'BESA spherical .elp file';
- chanformat(2).description = [ 'BESA spherical coordinate file. Note that BESA spherical coordinates ' ...
- 'are different from Matlab spherical coordinates' ];
- chanformat(2).skipline = 0; % some BESA files do not have headers
- chanformat(2).importformat = { 'type' 'labels' 'sph_theta_besa' 'sph_phi_besa' 'sph_radius' };
- % ---------------------------------------------------------------------------------------------------
- chanformat(3).type = 'xyz';
- chanformat(3).typestring = 'Matlab .xyz file';
- chanformat(3).description = [ 'Standard 3-D cartesian coordinate files with electrode labels in ' ...
- 'the first column and X, Y, and Z coordinates in columns 2, 3, and 4' ];
- chanformat(3).importformat = { 'channum' '-Y' 'X' 'Z' 'labels'};
- % ---------------------------------------------------------------------------------------------------
- chanformat(4).type = 'sfp';
- chanformat(4).typestring = 'BESA or EGI 3-D cartesian .sfp file';
- chanformat(4).description = [ 'Standard BESA 3-D cartesian coordinate files with electrode labels in ' ...
- 'the first column and X, Y, and Z coordinates in columns 2, 3, and 4.' ...
- 'Coordinates are re-oriented to fit the EEGLAB standard of having the ' ...
- 'nose along the +X axis.' ];
- chanformat(4).importformat = { 'labels' '-Y' 'X' 'Z' };
- chanformat(4).skipline = 0;
- % ---------------------------------------------------------------------------------------------------
- chanformat(5).type = 'loc';
- chanformat(5).typestring = 'EEGLAB polar .loc file';
- chanformat(5).description = [ 'EEGLAB polar .loc file' ];
- chanformat(5).importformat = { 'channum' 'theta' 'radius' 'labels' };
- % ---------------------------------------------------------------------------------------------------
- chanformat(6).type = 'sph';
- chanformat(6).typestring = 'Matlab .sph spherical file';
- chanformat(6).description = [ 'Standard 3-D spherical coordinate files in Matlab format' ];
- chanformat(6).importformat = { 'channum' 'sph_theta' 'sph_phi' 'labels' };
- % ---------------------------------------------------------------------------------------------------
- chanformat(7).type = 'asc';
- chanformat(7).typestring = 'Neuroscan polar .asc file';
- chanformat(7).description = [ 'Neuroscan polar .asc file, automatically recentered to fit EEGLAB standard' ...
- 'of having ''Cz'' at (0,0).' ];
- chanformat(7).importformat = 'readneurolocs';
- % ---------------------------------------------------------------------------------------------------
- chanformat(8).type = 'dat';
- chanformat(8).typestring = 'Neuroscan 3-D .dat file';
- chanformat(8).description = [ 'Neuroscan 3-D cartesian .dat file. Coordinates are re-oriented to fit ' ...
- 'the EEGLAB standard of having the nose along the +X axis.' ];
- chanformat(8).importformat = 'readneurolocs';
- % ---------------------------------------------------------------------------------------------------
- chanformat(9).type = 'elc';
- chanformat(9).typestring = 'ASA .elc 3-D file';
- chanformat(9).description = [ 'ASA .elc 3-D coordinate file containing scanned electrode positions. ' ...
- 'User must select the direction ' ...
- 'for the nose after importing the data file.' ];
- chanformat(9).importformat = 'readeetraklocs';
- % ---------------------------------------------------------------------------------------------------
- chanformat(10).type = 'chanedit';
- chanformat(10).typestring = 'EEGLAB complete 3-D file';
- chanformat(10).description = [ 'EEGLAB file containing polar, cartesian 3-D, and spherical 3-D ' ...
- 'electrode locations.' ];
- chanformat(10).importformat = { 'channum' 'labels' 'theta' 'radius' 'X' 'Y' 'Z' 'sph_theta' 'sph_phi' ...
- 'sph_radius' 'type' };
- chanformat(10).skipline = 1;
- % ---------------------------------------------------------------------------------------------------
- chanformat(11).type = 'custom';
- chanformat(11).typestring = 'Custom file format';
- chanformat(11).description = 'Custom ASCII file format where user can define content for each file columns.';
- chanformat(11).importformat = '';
- % ---------------------------------------------------------------------------------------------------
- % ----- ADD MORE FORMATS HERE -----------------------------------------------------------------------
- % ---------------------------------------------------------------------------------------------------
- listcolformat = { 'labels' 'channum' 'theta' 'radius' 'sph_theta' 'sph_phi' ...
- 'sph_radius' 'sph_theta_besa' 'sph_phi_besa' 'gain' 'calib' 'type' ...
- 'X' 'Y' 'Z' '-X' '-Y' '-Z' 'custom1' 'custom2' 'custom3' 'custom4' 'ignore' 'not def' };
- % ----------------------------------
- % special mode for getting the info
- % ----------------------------------
- if isstr(filename) & strcmp(filename, 'getinfos')
- eloc = chanformat;
- labels = listcolformat;
- return;
- end;
- g = cm_eeg_finputcheck_20140226( varargin, ...
- { 'filetype' 'string' {} '';
- 'importmode' 'string' { 'eeglab' 'native' } 'eeglab';
- 'defaultelp' 'string' { 'besa' 'polhemus' } 'polhemus';
- 'skiplines' 'integer' [0 Inf] [];
- 'elecind' 'integer' [1 Inf] [];
- 'format' 'cell' [] {} }, 'readlocs');
- if isstr(g), error(g); end;
- if isstr(filename)
-
- % format auto detection
- % --------------------
- if strcmpi(g.filetype, 'autodetect'), g.filetype = ''; end;
- g.filetype = strtok(g.filetype);
- periods = find(filename == '.');
- fileextension = filename(periods(end)+1:end);
- g.filetype = lower(g.filetype);
- if isempty(g.filetype)
- switch lower(fileextension),
- case {'loc' 'locs' }, g.filetype = 'loc';
- case 'xyz', g.filetype = 'xyz';
- fprintf( [ 'WARNING: Matlab Cartesian coord. file extension (".xyz") detected.\n' ...
- 'If importing EGI Cartesian coords, force type "sfp" instead.\n'] );
- case 'sph', g.filetype = 'sph';
- case 'ced', g.filetype = 'chanedit';
- case 'elp', g.filetype = g.defaultelp;
- case 'asc', g.filetype = 'asc';
- case 'dat', g.filetype = 'dat';
- case 'elc', g.filetype = 'elc';
- case 'eps', g.filetype = 'besa';
- case 'sfp', g.filetype = 'sfp';
- otherwise, g.filetype = '';
- end;
- fprintf('readlocs(): ''%s'' format assumed from file extension\n', g.filetype);
- else
- if strcmpi(g.filetype, 'locs'), g.filetype = 'loc'; end
- if strcmpi(g.filetype, 'eloc'), g.filetype = 'loc'; end
- end;
-
- % assign format from filetype
- % ---------------------------
- if ~isempty(g.filetype) & ~strcmpi(g.filetype, 'custom') ...
- & ~strcmpi(g.filetype, 'asc') & ~strcmpi(g.filetype, 'elc') & ~strcmpi(g.filetype, 'dat')
- indexformat = strmatch(lower(g.filetype), { chanformat.type }, 'exact');
- g.format = chanformat(indexformat).importformat;
- if isempty(g.skiplines)
- g.skiplines = chanformat(indexformat).skipline;
- end;
- if isempty(g.filetype)
- error( ['readlocs() error: The filetype cannot be detected from the \n' ...
- ' file extension, and custom format not specified']);
- end;
- end;
-
- % import file
- % -----------
- if strcmp(g.filetype, 'asc') | strcmp(g.filetype, 'dat')
- eloc = readneurolocs( filename );
- eloc = rmfield(eloc, 'sph_theta'); % for the conversion below
- eloc = rmfield(eloc, 'sph_theta_besa'); % for the conversion below
- if isfield(eloc, 'type')
- for index = 1:length(eloc)
- type = eloc(index).type;
- if type == 69, eloc(index).type = 'EEG';
- elseif type == 88, eloc(index).type = 'REF';
- elseif type >= 76 & type <= 82, eloc(index).type = 'FID';
- else eloc(index).type = num2str(eloc(index).type);
- end;
- end;
- end;
- elseif strcmp(g.filetype, 'elc')
- eloc = readeetraklocs( filename );
- %eloc = read_asa_elc( filename ); % from fieldtrip
- %eloc = struct('labels', eloc.label, 'X', mattocell(eloc.pnt(:,1)'), 'Y', ...
- % mattocell(eloc.pnt(:,2)'), 'Z', mattocell(eloc.pnt(:,3)'));
- eloc = convertlocs(eloc, 'cart2all');
- eloc = rmfield(eloc, 'sph_theta'); % for the conversion below
- eloc = rmfield(eloc, 'sph_theta_besa'); % for the conversion below
- elseif strcmp(lower(g.filetype(1:end-1)), 'polhemus') | ...
- strcmp(g.filetype, 'polhemus')
- try,
- [eloc labels X Y Z]= readelp( filename );
- if strcmp(g.filetype, 'polhemusy')
- tmp = X; X = Y; Y = tmp;
- end;
- for index = 1:length( eloc )
- eloc(index).X = X(index);
- eloc(index).Y = Y(index);
- eloc(index).Z = Z(index);
- end;
- catch,
- disp('readlocs(): Could not read Polhemus coords. Trying to read BESA .elp file.');
- [eloc, labels, theta, radius, indices] = readlocs( filename, 'defaultelp', 'besa', varargin{:} );
- end;
- else
- % importing file
- % --------------
- if isempty(g.skiplines), g.skiplines = 0; end;
- if strcmpi(g.filetype, 'chanedit')
- array = loadtxt( filename, 'delim', 9, 'skipline', g.skiplines, 'blankcell', 'off');
- else
- array = load_file_or_array( filename, g.skiplines);
- end;
- if size(array,2) < length(g.format)
- fprintf(['readlocs() warning: Fewer columns in the input than expected.\n' ...
- ' See >> help readlocs\n']);
- elseif size(array,2) > length(g.format)
- fprintf(['readlocs() warning: More columns in the input than expected.\n' ...
- ' See >> help readlocs\n']);
- end;
-
- % removing lines BESA
- % -------------------
- if isempty(array{1,2})
- disp('BESA header detected, skipping three lines...');
- array = load_file_or_array( filename, g.skiplines-1);
- if isempty(array{1,2})
- array = load_file_or_array( filename, g.skiplines-1);
- end;
- end;
- % xyz format, is the first col absent
- % -----------------------------------
- if strcmp(g.filetype, 'xyz')
- if size(array, 2) == 4
- array(:, 2:5) = array(:, 1:4);
- end;
- end;
-
- % removing comments and empty lines
- % ---------------------------------
- indexbeg = 1;
- while isempty(array{indexbeg,1}) | ...
- (isstr(array{indexbeg,1}) & array{indexbeg,1}(1) == '%' )
- indexbeg = indexbeg+1;
- end;
- array = array(indexbeg:end,:);
-
- % converting file
- % ---------------
- for indexcol = 1:min(size(array,2), length(g.format))
- [str mult] = checkformat(g.format{indexcol});
- for indexrow = 1:size( array, 1)
- if mult ~= 1
- eval ( [ 'eloc(indexrow).' str '= -array{indexrow, indexcol};' ]);
- else
- eval ( [ 'eloc(indexrow).' str '= array{indexrow, indexcol};' ]);
- end;
- end;
- end;
- end;
-
- % handling BESA coordinates
- % -------------------------
- if isfield(eloc, 'sph_theta_besa')
- if isfield(eloc, 'type')
- if isnumeric(eloc(1).type)
- disp('BESA format detected ( Theta | Phi )');
- for index = 1:length(eloc)
- eloc(index).sph_phi_besa = eloc(index).labels;
- eloc(index).sph_theta_besa = eloc(index).type;
- eloc(index).labels = '';
- eloc(index).type = '';
- end;
- eloc = rmfield(eloc, 'labels');
- end;
- end;
- if isfield(eloc, 'labels')
- if isnumeric(eloc(1).labels)
- disp('BESA format detected ( Elec | Theta | Phi )');
- for index = 1:length(eloc)
- eloc(index).sph_phi_besa = eloc(index).sph_theta_besa;
- eloc(index).sph_theta_besa = eloc(index).labels;
- eloc(index).labels = eloc(index).type;
- eloc(index).type = '';
- eloc(index).radius = 1;
- end;
- end;
- end;
-
- try
- eloc = convertlocs(eloc, 'sphbesa2all');
- eloc = convertlocs(eloc, 'topo2all'); % problem with some EGI files (not BESA files)
- catch, disp('Warning: coordinate conversion failed'); end;
- fprintf('Readlocs: BESA spherical coords. converted, now deleting BESA fields\n');
- fprintf(' to avoid confusion (these fields can be exported, though)\n');
- eloc = rmfield(eloc, 'sph_phi_besa');
- eloc = rmfield(eloc, 'sph_theta_besa');
- % converting XYZ coordinates to polar
- % -----------------------------------
- elseif isfield(eloc, 'sph_theta')
- try
- eloc = convertlocs(eloc, 'sph2all');
- catch, disp('Warning: coordinate conversion failed'); end;
- elseif isfield(eloc, 'X')
- try
- eloc = convertlocs(eloc, 'cart2all');
- catch, disp('Warning: coordinate conversion failed'); end;
- else
- try
- eloc = convertlocs(eloc, 'topo2all');
- catch, disp('Warning: coordinate conversion failed'); end;
- end;
-
- % inserting labels if no labels
- % -----------------------------
- if ~isfield(eloc, 'labels')
- fprintf('readlocs(): Inserting electrode labels automatically.\n');
- for index = 1:length(eloc)
- eloc(index).labels = [ 'E' int2str(index) ];
- end;
- else
- % remove trailing '.'
- for index = 1:length(eloc)
- if isstr(eloc(index).labels)
- tmpdots = find( eloc(index).labels == '.' );
- eloc(index).labels(tmpdots) = [];
- end;
- end;
- end;
-
- % resorting electrodes if number not-sorted
- % -----------------------------------------
- if isfield(eloc, 'channum')
- if ~isnumeric(eloc(1).channum)
- error('Channel numbers must be numeric');
- end;
- allchannum = [ eloc.channum ];
- if any( sort(allchannum) ~= allchannum )
- fprintf('readlocs(): Re-sorting channel numbers based on ''channum'' column indices\n');
- [tmp newindices] = sort(allchannum);
- eloc = eloc(newindices);
- end;
- eloc = rmfield(eloc, 'channum');
- end;
- else
- if isstruct(filename)
- eloc = filename;
- else
- disp('readlocs(): input variable must be a string or a structure');
- end;
- end;
- if ~isempty(g.elecind)
- eloc = eloc(g.elecind);
- end;
- if nargout > 2
- if isfield(eloc, 'theta')
- tmptheta = { eloc.theta }; % check which channels have (polar) coordinates set
- else tmptheta = cell(1,length(eloc));
- end;
- if isfield(eloc, 'theta')
- tmpx = { eloc.X }; % check which channels have (polar) coordinates set
- else tmpx = cell(1,length(eloc));
- end;
-
- indices = find(~cellfun('isempty', tmptheta));
- indices = intersect(find(~cellfun('isempty', tmpx)), indices);
- indices = sort(indices);
-
- indbad = setdiff(1:length(eloc), indices);
- tmptheta(indbad) = { NaN };
- theta = [ tmptheta{:} ];
- end;
- if nargout > 3
- if isfield(eloc, 'theta')
- tmprad = { eloc.radius }; % check which channels have (polar) coordinates set
- else tmprad = cell(1,length(eloc));
- end;
- tmprad(indbad) = { NaN };
- radius = [ tmprad{:} ];
- end;
- %tmpnum = find(~cellfun('isclass', { eloc.labels }, 'char'));
- %disp('Converting channel labels to string');
- for index = 1:length(eloc)
- if ~isstr(eloc(index).labels)
- eloc(index).labels = int2str(eloc(index).labels);
- end;
- end;
- labels = { eloc.labels };
- if isfield(eloc, 'ignore')
- eloc = rmfield(eloc, 'ignore');
- end;
- % process fiducials if any
- % ------------------------
- fidnames = { 'nz' 'lpa' 'rpa' 'nasion' 'left' 'right' 'nazion' 'fidnz' 'fidt9' 'fidt10' };
- for index = 1:length(fidnames)
- ind = strmatch(fidnames{index}, lower(labels), 'exact');
- if ~isempty(ind), eloc(ind).type = 'FID'; end;
- end;
- return;
- % interpret the variable name
- % ---------------------------
- function array = load_file_or_array( varname, skiplines );
- if isempty(skiplines),
- skiplines = 0;
- end;
- if exist( varname ) == 2
- array = loadtxt(varname,'verbose','off','skipline',skiplines,'blankcell','off');
- else % variable in the global workspace
- % --------------------------
- try, array = evalin('base', varname);
- catch, error('readlocs(): cannot find the named file or variable, check syntax');
- end;
- end;
- 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, 'ignore'), 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, 'custom1'), return; end;
- if strcmpi(str, 'custom2'), return; end;
- if strcmpi(str, 'custom3'), return; end;
- if strcmpi(str, 'custom4'), return; end;
- error(['readlocs(): undefined field ''' str '''']);
-
|