Home > eeg > eeglab_petrmods > old > importevent.m

importevent

PURPOSE ^

importevent() - Import experimental events from data file or Matlab

SYNOPSIS ^

function event = importevent(event, oldevent, srate, varargin);

DESCRIPTION ^

 importevent() - Import experimental events from data file or Matlab
                 array into a structure.

 Usage: >> eventstruct = importevent( event, oldevent, srate);
        >> eventstruct = importevent( event, oldevent, srate, 'key1', 'value1', ...);

 Input:
   event     - [ 'filename'|array ] Filename of a text file, or name of
               Matlab array in the global workspace containing an
               array of events in the folowing format: The first column
               is the type of the event, the second the latency. 
               The others are user-defined. The function can read 
               either numeric or text entries in ascii files.
   oldevent  - Old event structure. Used for aligning new events with old
               ones. Enter [] is no such structure exist.
   srate     - Sampling rate of the underlying data. Event latencies are
               expressed in terms of latency in sample point with respect
               to the data.

 Optional file or array input:
  'fields'   - [Cell array] List of the name of each user-defined column, 
               optionally followed by a description. Ex: { 'type', 'latency' }
  'skipline' - [Interger] Number of header rows to skip in the text file 
  'timeunit' - [ latency unit rel. to seconds ]. Default unit is 1 = seconds. 
  'delim'    - [string] String of delimiting characters in the input file. 
               Default is tab|space.

 Optional oldevent input:
  'append'   - ['yes'|'no'] 'yes' = Append events to the current events in 
               the EEG dataset {default}: 'no' = Erase the previous events.
  'indices'  - {integer vector] Vector indicating the indices of the events to
               modify. 
  'align'    - [num] Align the first event latency to the latency of existing 
               event number (num), and check latency consistency. See also the
               GUI help above.
  'optimalign' - ['on'|'off'] Optimize the sampling rate of the new events so
               they best align with old events. Default is 'on'.

 Outputs:
   eventstruct - Event structure containing imported events

 Example: >> eventstruct = importevent( 'event_values.txt', [], 256, ...
         'fields', {'type', 'latency','condition' }, ...
         'append', 'no', 'align', 0, 'timeunit', 1E-3 );

         This loads the ascii file 'event_values.txt' containing 3 columns
         (event_type, latency, and condition). Latencies in the file are
         in ms (1E-3). The first event latency is re-aligned with the
         beginning of the dataset ('align', 0). Any previous events
         are erased ('append', 'no').

 Author: Arnaud Delorme & Scott Makeig, CNL / Salk Institute, 2004

 See also: pop_importevent()

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % importevent() - Import experimental events from data file or Matlab
0002 %                 array into a structure.
0003 %
0004 % Usage: >> eventstruct = importevent( event, oldevent, srate);
0005 %        >> eventstruct = importevent( event, oldevent, srate, 'key1', 'value1', ...);
0006 %
0007 % Input:
0008 %   event     - [ 'filename'|array ] Filename of a text file, or name of
0009 %               Matlab array in the global workspace containing an
0010 %               array of events in the folowing format: The first column
0011 %               is the type of the event, the second the latency.
0012 %               The others are user-defined. The function can read
0013 %               either numeric or text entries in ascii files.
0014 %   oldevent  - Old event structure. Used for aligning new events with old
0015 %               ones. Enter [] is no such structure exist.
0016 %   srate     - Sampling rate of the underlying data. Event latencies are
0017 %               expressed in terms of latency in sample point with respect
0018 %               to the data.
0019 %
0020 % Optional file or array input:
0021 %  'fields'   - [Cell array] List of the name of each user-defined column,
0022 %               optionally followed by a description. Ex: { 'type', 'latency' }
0023 %  'skipline' - [Interger] Number of header rows to skip in the text file
0024 %  'timeunit' - [ latency unit rel. to seconds ]. Default unit is 1 = seconds.
0025 %  'delim'    - [string] String of delimiting characters in the input file.
0026 %               Default is tab|space.
0027 %
0028 % Optional oldevent input:
0029 %  'append'   - ['yes'|'no'] 'yes' = Append events to the current events in
0030 %               the EEG dataset {default}: 'no' = Erase the previous events.
0031 %  'indices'  - {integer vector] Vector indicating the indices of the events to
0032 %               modify.
0033 %  'align'    - [num] Align the first event latency to the latency of existing
0034 %               event number (num), and check latency consistency. See also the
0035 %               GUI help above.
0036 %  'optimalign' - ['on'|'off'] Optimize the sampling rate of the new events so
0037 %               they best align with old events. Default is 'on'.
0038 %
0039 % Outputs:
0040 %   eventstruct - Event structure containing imported events
0041 %
0042 % Example: >> eventstruct = importevent( 'event_values.txt', [], 256, ...
0043 %         'fields', {'type', 'latency','condition' }, ...
0044 %         'append', 'no', 'align', 0, 'timeunit', 1E-3 );
0045 %
0046 %         This loads the ascii file 'event_values.txt' containing 3 columns
0047 %         (event_type, latency, and condition). Latencies in the file are
0048 %         in ms (1E-3). The first event latency is re-aligned with the
0049 %         beginning of the dataset ('align', 0). Any previous events
0050 %         are erased ('append', 'no').
0051 %
0052 % Author: Arnaud Delorme & Scott Makeig, CNL / Salk Institute, 2004
0053 %
0054 % See also: pop_importevent()
0055 
0056 %123456789012345678901234567890123456789012345678901234567890123456789012
0057 
0058 % Copyright (C) Arnaud Delorme, CNL / Salk Institute, 2004, arno@salk.edu
0059 %
0060 % This program is free software; you can redistribute it and/or modify
0061 % it under the terms of the GNU General Public License as published by
0062 % the Free Software Foundation; either version 2 of the License, or
0063 % (at your option) any later version.
0064 %
0065 % This program is distributed in the hope that it will be useful,
0066 % but WITHOUT ANY WARRANTY; without even the implied warranty of
0067 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0068 % GNU General Public License for more details.
0069 %
0070 % You should have received a copy of the GNU General Public License
0071 % along with this program; if not, write to the Free Software
0072 % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0073 
0074 % $Log: importevent.m,v
0075 
0076 function event = importevent(event, oldevent, srate, varargin);
0077 
0078 if nargin < 1
0079    help importevent;
0080    return;
0081 end;    
0082 
0083 I = [];
0084 
0085 % remove the event field
0086 % ----------------------
0087 if ~isempty(oldevent), allfields = fieldnames(oldevent);
0088 else                   allfields = {}; end;
0089     
0090 g = finputcheck( varargin, { 'fields'    'cell'     []         {};
0091                          'skipline'  'integer'  [0 Inf]    0;
0092                          'indices'   'integer'  [1 Inf]    [];
0093                          'append'    'string'   {'yes' 'no' '''yes''' '''no''' }         'yes';
0094                          'timeunit'  'real'     [0 Inf]    1;
0095                          'event'     { 'real' 'string' }     []    [];
0096                          'align'     'integer'  []         NaN;
0097                          'optimalign' 'string'  { 'on' 'off' }         'on';
0098                          'delim'     {'integer' 'string'}   []         char([9 32])}, 'importevent');
0099 if isstr(g), error(g); end;
0100 if ~isempty(g.indices), g.append = 'yes'; end;
0101 g.delim = char(g.delim);    
0102 
0103 % call from pop_importevent
0104 % -------------------------
0105 if ~isempty(g.event)
0106     event = g.event;
0107 end;
0108 
0109 % determine latency for old event alignment
0110 % -----------------------------------------
0111 g.align.val = g.align;
0112 if ~isnan(g.align.val)
0113     if isempty(oldevent)
0114         error('Setevent: no pre-existing event, cannot perform alignment');
0115     end;    
0116     if ~isfield(oldevent, 'latency')
0117         error('Setevent: pre-existing events do not have a latency field for re-alignment');
0118     end;    
0119     switch g.append
0120         case {'yes' '''yes'''}, disp('Setevent warning: using align, events should not be appended but erased');
0121     end;
0122     if g.align.val < 0
0123         g.align.event = oldevent(1).latency;
0124     else
0125         g.align.event = oldevent(g.align.val+1).latency;
0126     end
0127     g.align.nbevent = length(oldevent);
0128     g.oldevents = oldevent;
0129     g.align.txt = sprintf([ 'Check alignment between pre-existing (old) and loaded event' ...
0130                           ' latencies:\nOld event latencies (10 first): %s ...\n' ], ...
0131                           int2str(cell2mat({ oldevent(1:min(10, length(oldevent))).latency })));
0132 else
0133     g.oldevents = [];
0134 end;
0135 
0136 tmpfields = fieldnames(g);
0137 event = oldevent;
0138 % scan all the fields of g
0139 % ------------------------
0140 for curfield = tmpfields'
0141     if ~isempty(event), allfields = fieldnames(event);
0142     else                    allfields = {}; end;
0143     switch lower(curfield{1})
0144         case {'append', 'fields', 'skipline', 'indices', 'timeunit', 'align', 'delim' }, ; % do nothing now
0145         case 'event', % load an ascii file
0146             switch g.append 
0147                 case { '''no''' 'no' } % ''no'' for backward compatibility
0148                       event = load_file_or_array( g.event, g.skipline, g.delim );
0149                       allfields = g.fields(1:min(length(g.fields), size(event,2)));
0150                       event = eeg_eventformat(event, 'struct', allfields);
0151                       % generate ori fields
0152                       % -------------------
0153                       for index = 1:length(event)
0154                           event(index).init_index = index;
0155                           event(index).init_time  = event(index).latency*g.timeunit;
0156                       end;
0157                       event = recomputelatency( event, 1:length(event), srate, ...
0158                                                     g.timeunit, g.align, g.oldevents, g.optimalign);
0159                 case { '''yes''' 'yes' }
0160                       % match existing fields
0161                       % ---------------------
0162                       tmparray = load_file_or_array( g.event, g.skipline, g.delim );
0163                       if isempty(g.indices) g.indices = [1:size(tmparray,1)] + length(event); end;
0164                       if length(g.indices) ~= size(tmparray,1)
0165                             error('Set error: number of row in file does not match the number of event given as input'); 
0166                       end;
0167 
0168                       % add field
0169                       % ---------
0170                       g.fields = getnewfields( g.fields, size(tmparray,2)-length(g.fields));
0171                       
0172                       % add new values
0173                       % ---------------------
0174                       for eventfield = 1:size(tmparray,2)
0175 
0176             % August 8, 2005 - Petr Janata
0177             % The code was only copying the first letter of strings
0178             % that were being passed as event type names
0179             event = setstruct( event, g.fields{eventfield}, g.indices, tmparray(:,eventfield));
0180                         
0181 %             if isstr(tmparray{1,eventfield})
0182 %                  for indtmp = 1:length(g.indices)
0183 %                     event = setstruct( event, g.fields{eventfield}, g.indices(indtmp), tmparray{indtmp,eventfield});
0184 %                end;
0185 %             else
0186 %               % event = setstruct( event, g.fields{eventfield}, g.indices, cell2mat(tmparray(:,eventfield)));
0187 %             end;
0188                       end;      
0189                       % generate ori fields
0190                       % -------------------
0191                       offset = length(event)-size(tmparray,2);
0192                       for index = 1:size(tmparray,2)
0193                           event(index+offset).init_index = index;
0194                           event(index+offset).init_time  = event(index+offset).latency*g.timeunit;
0195                       end;
0196                       event = recomputelatency( event, g.indices, srate, g.timeunit, ...
0197                                                     g.align, g.oldevents, g.optimalign);
0198             end;
0199       end;
0200 end;
0201 
0202 if isempty(event) % usefull 0xNB empty structure
0203     event = [];
0204 end;
0205 
0206 % remove the events wit out-of-bound latencies
0207 % --------------------------------------------
0208 if isfield(event, 'latency')
0209     try 
0210         res = cellfun('isempty', { event.latency });
0211         res = find(res);
0212         if ~isempty(res)
0213             fprintf( 'importevent warning: %d/%d have invalid latencies and were removed\n', ...
0214                      length(res), length(event));
0215             event( res ) = [];
0216         end;
0217     end;
0218 end;
0219 
0220 % interpret the variable name
0221 % ---------------------------While this architecture allows for an extensible framework of functions to be built which support the computations and properties associated with that node, the current version solely implements assignment of waveforms.
0222 function array = load_file_or_array( varname, skipline, delim );
0223     if isstr(varname) & exist(varname) == 2  % mean that it is a filename
0224                                              % --------------------------
0225         array = loadtxt( varname, 'skipline', skipline, 'delim', delim );
0226         
0227     else % variable in the global workspace
0228          % --------------------------
0229          if isstr(varname)
0230              array = evalin('base', varname);
0231              if ~iscell(array)
0232                  array = mat2cell(array, ones(1, size(array,1)), ones(1, size(array,2)));
0233              end;    
0234          else
0235              array = varname;
0236          end;
0237     end;     
0238 return;
0239 
0240 % update latency values
0241 % ---------------------
0242 function event = recomputelatency( event, indices, srate, timeunit, align, oldevents, optimalign);
0243 
0244     % update time unit
0245     % ----------------
0246     if ~isfield(event, 'latency'), 
0247         if isfield(event, 'duration')
0248             error('A duration field cannot be defined if a latency field has not been defined');
0249         end;
0250         return; 
0251     end;
0252     for index = indices
0253         event(index).latency  = event(index).latency*srate*timeunit;
0254         if isfield(event, 'duration')
0255             event(index).duration = event(index).duration*srate*timeunit;
0256         end;
0257     end;
0258 
0259     % alignment with old events
0260     % -------------------------
0261     if ~isnan( align.val )
0262         if align.val >= 0, alignlatency = event(1).latency;
0263         else               alignlatency = event(-align.val+1).latency;
0264         end;
0265         for index = indices
0266              event(index).latency = event(index).latency-alignlatency+align.event;
0267         end;
0268         if length(event) ~= align.nbevent
0269             disp([ 'Setevent warning: the number of pre-existing events do not correspond to the ' ...
0270                    'number of event that were read, so their latencies may have been wrongly re-aligned' ]);
0271         end;           
0272         fprintf(align.txt);
0273         fprintf('New event latencies (10 first): %s ...\n', int2str(round(cell2mat({ event(1:min(10, length(event))).latency }))));
0274     end;
0275     if strcmpi(optimalign, 'on') & ~isempty(oldevents)
0276         newlat = cell2mat({ event.latency     });
0277         oldlat = cell2mat({ oldevents.latency });
0278        
0279         newlat = repmat(newlat, [length(oldlat) 1]);
0280         oldlat = repmat(oldlat', [1 size(newlat,2)]);
0281         if align.val >= 0
0282             newlat = newlat-newlat(1);
0283             oldlat = oldlat-oldlat(1+align.val);
0284         else
0285             newlat = newlat-newlat(1-align.val);
0286             oldlat = oldlat-oldlat(1);
0287         end;
0288         
0289         newfactor = fminsearch('eventalign',1,[],newlat, oldlat);
0290         fprintf('Best sampling rate ratio found is %1.7f. Below latencies after adjustment\n', newfactor);
0291         if newfactor > 1.01 | newfactor < 0.99
0292             disp('Difference is more than 1%, something is wrong; ignoring ratio');
0293             newfactor = 1;
0294         end;
0295         
0296         %diffarray = abs(newfactor*newlat-oldlat)';
0297         %[allmins poss] = min(diffarray);
0298         %figure; hist(allmins);
0299     else
0300         newfactor = 1;
0301     end;
0302     if ~isnan( align.val ) & newfactor ~= 1 
0303         if align.val >= 0
0304             latfirstevent = event(1).latency;
0305         else
0306             latfirstevent = event(-align.val+1).latency;
0307         end;
0308         for index = setdiff(indices, 1)
0309             event(index).latency = round(event(index).latency-latfirstevent)*newfactor+latfirstevent;
0310         end;
0311         if ~isempty(oldevents)
0312             fprintf('Old event latencies (10 first): %s ...\n', int2str(round(cell2mat({ event(1:min(10, length(event))).latency }))));
0313             fprintf('New event latencies (10 first): %s ...\n', int2str(round(cell2mat({ oldevents(1:min(10, length(oldevents))).latency }))));
0314         end;
0315     else
0316         % must add one (because first sample point has latency 0
0317         % ------------------------------------------------------
0318         for index = indices
0319             event(index).latency = round((event(index).latency+1)*1000*newfactor)/1000;
0320         end;
0321     end;        
0322 
0323          
0324 % create new field names
0325 % ----------------------
0326 function epochfield = getnewfields( epochfield, nbfields )
0327    count = 1;
0328    while nbfields > 0
0329        if isempty( strmatch([ 'var' int2str(count) ], epochfield ) )
0330                epochfield =  { epochfield{:} [ 'var' int2str(count) ] };
0331                nbfields = nbfields-1;
0332        else    count = count+1;
0333        end;                    
0334    end;     
0335 return;
0336     
0337 function var = setstruct( var, fieldname, indices, values )
0338     if exist('indices') ~= 1, indices = 1:length(var); end;
0339     for index = 1:length(indices)
0340         var = setfield(var, {indices(index)}, fieldname, values{index});
0341 %        var = setfield(var, {indices(index)}, fieldname, values(index));
0342     end;
0343 return;

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003