% POP_ERPIMAGE - draw an ERP-image plot of a given EEG channel or independent
%                  component. Uses a pop-up window if less than three (or four
%                  in one condition) input arguments are supplied. Calls ERPIMAGE.
%                  For further details see >> help erpimage
% Usage:
%   >> pop_erpimage(EEG, typeplot);          % pop-up a data entry window
%   >> pop_erpimage(EEG, typeplot, lastcom); % pop-up a data entry window
%   >> pop_erpimage(EEG, typeplot, channel); % no pop-up window
%   >> pop_erpimage(EEG, typeplot, channel, projchan, title, ...
%                  smooth, decimate, sortingtype, sortingwin, ...
%                            sortingeventfield, renorm, options...);
% Graphic interface:
%   "Channel or Component" - [edit box] Enter channel number or component
%                 number to plot. ERPIMAGE equivalent: 'channel'
%   "Project to channel #" - [edit box] (for plotting independent components).
%                 Allow reprojecting the component activity
%                 to a given channel or group of channels.
%                 ERPIMAGE equivalent: [none]
%   "Smoothing" - [text box] Smoothing parameter in number of trials.
%                 ERPIMAGE equivalent: 'smooth'
%   "Downsampling" - [edit box] Decimate parameter.
%                 ERPIMAGE equivalent: 'decimate'
%   "Time limits" - [edit box] Enter the time limits in milliseconds.
%                 ERPIMAGE equivalent: the 1st and 2nd parameters of the 'limit' array
%   "Figure title" - [edit box] Enter the figure title here.  If empty, a title
%                 is automatically generated. ERPIMAGE equivalent: 'title'
%   "Plot scalp map" - [checkbox] Setting this option plot a scalp map of the
%                 channel location (or component topography) next to the
%                 erpimage. ERPIMAGE equivalent: 'topo'
%   "plot ERP" - [checkbox] Setting this option plot the channel or component
%                 ERP below the ERP image. ERPIMAGE equivalent: 'erp'
%   "Plot colorbar" - [checkbox] Plot the colorbar on the right of the erpimage.
%                 ERPIMAGE equivalent: 'cbar'
%   "ERP limits" - [edit box] Set the minimum and maximum value for the ERP plot
%                 ERPIMAGE equivalent: 3rd and 4th parameters of the 'limit' array
%   "Color limits" - [edit box] Set the color limits for the ERP image.
%                 ERPIMAGE equivalent: 'caxis'
%   "Epoch sorting field" - [button and edit box] Specify the event field which
%                 values will be used to sort the trials. For instance, if you
%                 select the 'latency' fields, trials will be sorted by the
%                 latency of the selected events.
%                 ERPIMAGE equivalent: 'sortingeventfield'
%   "Event type(s)" - [button and edit box] Specify which event subset to select,
%                 based on the event 'type' field values (to scan for event types, use
%                 menu Edit > Events values and look at the values of the 'type'
%                 field). For instance, entering type 'rt' (if defined) and field
%                 'latency' in option above will sort trials on reaction time latencies.
%                 When several selected events are present in individual trials,
%                 the first event values are used for sorting and a warning is issued.
%                 ERPIMAGE equivalent: 'sortingtype'
%   "Event time range" - [edit box] Specify which event subset to select based on
%                 event latency values. As the option above, this further restrains
%                 the selection of events. For example, entering [200 300] in this
%                 box, 'rt' for the event type (above), and 'latency' for the
%                 epoch sorting field will select trials with reaction-time latencies
%                 in between 200 and 300 ms. Trials with no such event will not be
%                 included in the ERP-image plot. ERPIMAGE equivalent: 'sortingwin'
%   "rescale" - [edit box] 'yes', 'no', or a Matlab formula.
%                 ERPIMAGE equivalent: 'renorm'
%   "align" - [edit box] Set this to 'Inf' to re-align the individual trials
%                 on the median latency of the selected events. Else, enter an epoch time
%                 (in ms) to align the events to (Ex: 0). ERPIMAGE equivalent: 'align'
%   "Don't sort by value" - [checkbox] Check this box if you do not want to
%                 sort the trials but do want to plot the selected event values.
%                 ERPIMAGE equivalent: 'nosort'
%   "Don't plot value" - [checkbox] Check this box if you do not want to
%                 plot the selected event values, but still want to sort
%                 the data trials according to these values.
%                 ERPIMAGE equivalent: 'noplot'
%   "Sort by phase > Frequency" - [edit box] Specify the frequency or frequency
%                 range for sorting trials by phase. ERPIMAGE equivalent:
%                 3rd and 4th inputs to 'phasesort'
%   "Window center (ms)" - [edit box] ERPIMAGE equivalent: 1st 'phasesort' input
%   "Percent low-amp. trials to ignore" - [edit box] ERPIMAGE equivalent:
%                 2nd 'phasesort' input
%   "Wavelet cycles" - [text] Number of wavelet cycles used for spectral decomposition
%                 at the specified latency. To change this, see "More options" {default: 3}
%   "Inter-trial coherence options > Frequency" - [edit box] Frequency at which
%                 to compute coherence. Constrained to be the same as the
%                 "Sort by phase > Frequency" edit box. ERPIMAGE equivalent: 'coher'
%   "Signif. level" - [edit box] Coherence significance cutoff, as a proability
%                  (Ex: .05). ERPIMAGE equivalent: 'signif'
%   "Amplitude limit" - [edit box] Amplitude limits [min max] for the data power
%                 plot at the selected frequency. ERPIMAGE equivalent:
%                 5th and 6th inputs to 'limit'
%   "Coher limits" - [edit box] Upper limit (<=1) for the coherence
%                 plot. ERPIMAGE equivalent: 7th and 8th inputs of 'limit'
%   "Image amps" - [checkbox] Check this box for plotting the spectral amplitude
%                 image at the selected frequency (instead of plotting EEG potential).
%                 ERPIMAGE equivalent: 'plotamp'
%   "Plot spectrum" - [edit box] Plot the channel or component data spectrum in
%                 the top right corner of the ERP image. ERPIMAGE equivalent: 'spec'
%   "Baseline ampl." - [edit box] Baseline amplitude for data power plot at the
%                 selected frequency. ERPIMAGE equivalent: 7th inputs of 'limit'
%   "Mark times" - [edit box] Time(s) in ms to plot vertical lines.
%                 ERPIMAGE equivalent: 'vert'
%   "More options" - [edit box] Enter 'key', 'value' sequences. Other ERPIMAGE
%                 options not handled by this interface, including: 'erpstd' to
%                 plot the ERP standard deviation; 'auxvar' to plot auxiliary
%                 variables; 'ampsort' to sort trials based on amplitude at
%                 the selected frequency, etc.  For further information see
%                 >> help ERPIMAGE
% Inputs:
%   EEG        - dataset structure
%   typeplot   - 1=channel, 0=component {default: 1}
%   lastcom    - string containing previous pop_erpimage command (from LASTCOM)
%                or from the previous function call output.  The values from this
%                function call are used as default in the graphic interface.
%
% Commandline options:
%   channel    - Index of channel or component(s) to plot {default: 1}
%   projchan   - Channel to back-project the selected component(s) to.
%                If plotting channel activity, this argument is ignored.
%                If [], the ICA component activation is plotted {default []}.
%   title      - ['string'] Plot title {default: []}
%   smooth     - Smoothing parameter (number of trials). {Default: 5}
%                ERPIMAGE equivalent: 'avewidth'
%   decimate   - Decimate parameter (i.e. ratio of trials_in/trials_out).
%                ERPAIMGE equivalent: 'decimate' {Default: 0}
%   sortingtype - Sorting event type(s) ([int vector]; []=all). See Notes below.
%                Either a string or an integer.
%   sortingwin - Sorting event window [start, end] in seconds ([]=whole epoch)
%   sortingeventfield - Sorting field name. {default: none}. See Notes below.
%   options    - ERPIMAGE options, separated by commas (Ex: 'erp', 'cbar').
%                {Default: none}. For further details see >> erpimage help
%
% Outputs from pop-up:
%   String containing the command used to evaluate this plotting function
%   (saved by EEGLAB as LASTCOM). Enter it as the 'lastcom' input to restore
%   the previous parameters as defaults in a new POP_ERPIMAGE pop-up window
%
% Outputs from commandline:
%   Same as ERPIMAGE. Note: No outputs are returned when a window pops-up
%   to ask for additional arguments
%
% Notes:
%   1) A new figure is created only when the pop-up window is called,
%      so you may call this command with >3 args to draw in SBPLOT axes.
%   2) To sort epochs, first define the event field to be used with
%      the argument 'sortingeventfield' (for instance 'latency'). Then,
%      because there may be several events with different latencies in a
%      given epoch, it is possible to consider only a subsets of events
%      using the 'sortingtype' and 'sortingwin' arguments. The
%      'sortingtype' argument selects events with definite types. The
%      'sortingwin' argument helps to define a specific time window in the
%      epoch to select events. For instance the epoch time range may be -1
%      to 2 seconds but one may want to select events only in the range 0
%      to 1 second. These three parameters are forwarded to the function
%      EEG_GETEPOCHEVENT, whose help message contains more details.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: EEGLAB, ERPIMAGE, EEG_GETEPOCHEVENT

% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.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.

% 01-25-02 reformated help & license -ad
% 02-12-02 added new event format compatibility -ad
% 02-15-02 text interface editing -sm & ad
% 03-07-02 add the eeglab computeica options -ad
% 02-15-02 modified the function according to the new event/epoch structure -ad
% 03-18-02 added title -ad & sm
% 04-04-02 added outputs -ad & sm

function varargout = pop_erpimage( EEG, typeplot, channel, projchan, titleplot, smooth, decimate, sortingtype, ...
            sortingwin, sortingeventfield, varargin)

varargout{1} = '';
if nargin < 1
   help pop_erpimage;
   return;
end

if typeplot == 0 && isempty(EEG.icasphere)
   error('no ICA data for this set, first run ICA');
end;
if EEG.trials == 1
   error('erpimage of one trial cannot be plotted');
end;

if nargin < 2
	typeplot = 1; %1=signal; 0=component
end
lastcom = [];
if nargin < 3
	popup = 1;
else
	popup = ischar(channel) | isempty(channel);
	if ischar(channel)
		lastcom = channel;
	end
end

opt = [];
if popup
	% get contextual help
	% -------------------
    erpimagefile = which('erpimage.m');
	[txt2 vars2] = gethelpvar(erpimagefile);
	txt  = { txt2{:}};
	vars = { vars2{:}};
	% [txt vars] = gethelpvar('erpimopt.m');
	% txt  = { txt{:} txt2{:}};
	% vars = { vars{:} vars2{:}};

    opt.topo         = getkeyval(lastcom, 'topo', 'present', 1);
    opt.fieldname    = getkeyval(lastcom, 10);
    opt.type         = getkeyval(lastcom, 8);
    opt.renorm       = getkeyval(lastcom, 'renorm','', 'no');
    opt.erp          = fastif(getkeyval(lastcom, '''erp''', 'present', 1), 'on', 'off');
    opt.cbar         = fastif(getkeyval(lastcom, 'cbar', 'present', 1), 'on', 'off');
    opt.nosort       = fastif(getkeyval(lastcom, 'nosort', 'present', 0), 'on', 'off');
    opt.noplot       = fastif(getkeyval(lastcom, 'noplot', 'present', 0), 'on', 'off');
    opt.plotamps     = fastif(getkeyval(lastcom, 'plotamps', 'present', 0), 'on', 'off');
    opt.index        = str2num(getkeyval(lastcom,3,[],'1'));
    opt.smoothing    = str2num(getkeyval(lastcom, 6, [], int2str(min(max(EEG.trials-5,0), 10))));
    opt.downsampling = str2num(getkeyval(lastcom, 7, [], '1'));
    opt.caxis        = str2num(getkeyval(lastcom, 'caxis'));
    opt.eventrange   = str2num(getkeyval(lastcom, 9));
    opt.align        = str2num(getkeyval(lastcom, 'align'));
    opt.phasesort    = str2num(getkeyval(lastcom, 'phasesort'));
    opt.coher        = str2num(getkeyval(lastcom, 'coher'));
    opt.spec         = str2num(getkeyval(lastcom, 'spec'));
    opt.vert         = str2num(getkeyval(lastcom, 'vert'));
    opt.limits       = str2num(getkeyval(lastcom, 'limits'));
    opt.limits       = [ opt.limits NaN NaN NaN NaN NaN NaN NaN NaN NaN ]; opt.limits = opt.limits(1:9);
    opt.coher        = [ opt.coher NaN NaN NaN NaN NaN NaN NaN NaN NaN ];  opt.coher  = opt.coher(1:3);
    opt.phasesort    = [ opt.phasesort NaN NaN NaN NaN NaN NaN NaN NaN NaN ]; opt.phasesort = opt.phasesort(1:4);
    if isnan(opt.limits(1)), opt.limits(1:2) = 1000*[EEG.xmin EEG.xmax]; end

	commandphase = [ 'if ~isempty(get(findobj(''parent'', gcbf, ''tag'', ''phase''),''string'')),' ...
					 '   if ~isempty(get(findobj(''parent'', gcbf, ''tag'', ''coher''),''string'')), ' ...
					 '      set(findobj(''parent'', gcbf, ''tag'', ''coher''), ''string'', get(findobj(''parent'', gcbf, ''tag'', ''phase''),''string''));' ...
					 'end; end;' ];
	commandcoher = [ 'if ~isempty(get(findobj(''parent'', gcbf, ''tag'', ''coher''),''string'')),' ...
					 '   if ~isempty(get(findobj(''parent'', gcbf, ''tag'', ''phase''),''string'')), ' ...
					 '      set(findobj(''parent'', gcbf, ''tag'', ''phase''), ''string'', get(findobj(''parent'', gcbf, ''tag'', ''coher''),''string''));' ...
					 'end; end;' ];

	commandfield = ['tmpEEG = get(gcbf, ''userdata''); if isempty(tmpEEG.event)' ...
				   '   errordlg2(''No events'');' ...
				   'else' ...
				   '   tmpfieldnames = fieldnames(tmpEEG.event);' ...
				   '   [tmps,tmpv] = listdlg2(''PromptString'', ''Select fields'', ''SelectionMode'',''single'',''ListString'', tmpfieldnames);' ...
				   '   if tmpv' ...
				   '       set(findobj(''parent'', gcbf, ''tag'', ''field''), ''string'', tmpfieldnames{tmps});' ...
				   '   end;' ...
				   'end;' ...
                   'if isempty(get(findobj(''parent'', gcbf, ''tag'', ''type''), ''string'')),' ...
                   '   warndlg2(''Do not forget to select an event type in the next edit box'');' ...
                   'end;' ...
				   'clear tmpEEG tmps tmpv tmpfieldnames;' ];
	commandtype = [ 'tmpEEG = get(gcbf, ''userdata''); if ~isfield(tmpEEG.event, ''type'')' ...
				   '   errordlg2(''No type field'');' ...
				   'else' ...
                   '   tmpevent = tmpEEG.event;' ...
                   '   if isnumeric(tmpEEG.event(1).type),' ...
				   '        [tmps,tmpstr] = pop_chansel(unique([ tmpevent.type ]));' ...
				   '   else,' ...
                   '        [tmps,tmpstr] = pop_chansel(unique({ tmpevent.type }));' ...
                   '   end;' ...
				   '   if ~isempty(tmps)' ...
				   '       set(findobj(''parent'', gcbf, ''tag'', ''type''), ''string'', tmpstr);' ...
				   '   end;' ...
				   'end;' ...
                   'if isempty(get(findobj(''parent'', gcbf, ''tag'', ''field''), ''string'')),' ...
                   '   warndlg2(''Do not forget to select an event type in the previous edit box'');' ...
                   'end;' ...
				   'clear tmpEEG tmps tmpv tmpstr tmpevent tmpfieldnames;' ];
    commandchan = 'tmpEEG = get(gcbf, ''userdata''); tmpchanlocs = tmpEEG(1).chanlocs; [tmp tmpval] = pop_chansel({tmpchanlocs.labels}, ''withindex'', ''on'', ''selectionmode'', ''single''); set(findobj(gcbf, ''tag'', ''chan''), ''string'',tmpval); clear tmpEEG tmp tmpchanlocs tmpval';

	geometry = { [1 1 0.4 0.5 2.1] [1 1 1 1 1] [1 1 1 1 1] [1 1 1 1 1] [1] [1] [1 1 1 0.8 0.8 1.2] [1 1 1 0.8 0.8 1.2] [1] [1] ...
				 [1.6 1.7 1.2 1 .5] [1.6 1.7 1.2 1 .5] [1] [1] [1.5 1 1 1 1] [1.5 1 1 1 1] [1] [1] [1.5 1 1 2.2] [1.5 1 1 2.2]};
    uilist = { { 'Style', 'text', 'string', fastif(typeplot, 'Channel', 'Component(s)'), 'fontweight', 'bold'  } ...
			   { 'Style', 'edit', 'string', num2str(opt.index), 'tag', 'chan' } ...
               { 'style' 'pushbutton' 'string'  '...', 'enable' fastif(~isempty(EEG(1).chanlocs) && typeplot, 'on', 'off') 'callback' commandchan } ...
			   { 'Style', 'text', 'string', 'Fig. title', 'fontweight', 'bold'  } ...
			   { 'Style', 'edit', 'string', '', 'tag', 'title'  } ...
			   ...
			   { 'Style', 'text', 'string', 'Smoothing', 'fontweight', 'bold', 'tooltipstring', context('avewidth',vars,txt) } ...
			   { 'Style', 'edit', 'string', num2str(opt.smoothing), 'tag', 'smooth' } ...
			   { 'Style', 'checkbox', 'string', 'Plot scalp map', 'tooltipstring', 'plot a 2-d head map (vector) at upper left', ...
				 'value', opt.topo, 'tag', 'plotmap'  } { } { } ...
			   { 'Style', 'text', 'string', 'Downsampling', 'fontweight', 'bold', 'tooltipstring', context('decimate',vars,txt) } ...
			   { 'Style', 'edit', 'string', num2str(opt.downsampling), 'tag', 'decimate' } ...
			   { 'Style', 'checkbox', 'string', 'Plot ERP', 'tooltipstring', context('erp',vars,txt), 'value', fastif(strcmpi(opt.erp, 'on'), 1,0), 'tag', 'erp' } ...
			   { 'Style', 'text', 'string', fastif(typeplot, 'ERP limits (uV)','ERP limits'), 'tooltipstring', [ 'Plotting limits for ERP trace [min_uV max_uV]' 10 '{Default: ERP data limits}']  } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.limits(3)), num2str(opt.limits(3:4)), ''), 'tag', 'limerp'  } ...
			   { 'Style', 'text', 'string', 'Time limits (ms)', 'fontweight', 'bold', 'tooltipstring',  'Select time subset in ms' } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.limits(1)), num2str(opt.limits(1:2)), ''), 'tag', 'limtime' } ...
			   { 'Style', 'checkbox', 'string', 'Plot colorbar','tooltipstring', context('caxis',vars,txt), 'value', fastif(strcmpi(opt.cbar, 'on'), 1,0), 'tag', 'cbar' } ...
			   { 'Style', 'text', 'string', 'Color limits (see Help)','tooltipstring', context('caxis',vars,txt) } ...
			   { 'Style', 'edit', 'string', num2str(opt.caxis), 'tag', 'caxis' } ...
			   {} ...
			   { 'Style', 'text', 'string', 'Sort/align trials by epoch event values', 'fontweight', 'bold'} ...
			   { 'Style', 'pushbutton', 'string', 'Epoch-sorting field', 'callback', commandfield, ...
				 'tooltipstring', 'Epoch-sorting event field name (Ex: latency; default: no sorting):' } ...
			   { 'Style', 'pushbutton', 'string', 'Event type(s)', 'callback', commandtype, 'tooltipstring', ['Event type(s) subset (default: all):' 10 ...
                '(See ''/Edit/Edit event values'' for event types)']  } ...
			   { 'Style', 'text', 'string', 'Event time range', 'tooltipstring', [ 'Sorting event window [start, end] in milliseconds (default: whole epoch):' 10 ...
												  'events are only selected within this time window (can be useful if several' 10 ...
												  'events of the same type are in the same epoch, or for selecting trials with given response time)']} ...
			   { 'Style', 'text', 'string', 'Rescale', 'tooltipstring', 'Rescale sorting variable to plot window (yes|no|a*x+b)(Ex:3*x+2):' } ...
			   { 'Style', 'text', 'string', 'Align', 'tooltipstring',  context('align',vars,txt) } ...
			   { 'Style', 'checkbox', 'string', 'Don''t sort by value', 'tooltipstring', context('nosort',vars,txt), 'value', fastif(strcmpi(opt.nosort, 'on'), 1,0), 'tag', 'nosort' } ...
			   { 'Style', 'edit', 'string', opt.fieldname, 'tag', 'field' } ...
			   { 'Style', 'edit', 'string', opt.type, 'tag', 'type' } ...
			   { 'Style', 'edit', 'string', num2str(opt.eventrange), 'tag', 'eventrange' } ...
			   { 'Style', 'edit', 'string', opt.renorm, 'tag', 'renorm' } ...
			   { 'Style', 'edit', 'string', num2str(opt.align),  'tag', 'align' } ...
			   { 'Style', 'checkbox', 'string', 'Don''t plot values', 'tooltipstring', context('noplot',vars,txt), 'value', fastif(strcmpi(opt.noplot, 'on'), 1,0), 'tag', 'noplot' } ...
			   {} ...
			   { 'Style', 'text', 'string', 'Sort trials by phase', 'fontweight', 'bold'} ...
			   { 'Style', 'text', 'string', 'Frequency (Hz | minHz maxHz)', 'tooltipstring', ['sort by phase at maximum-power frequency' 10 ...
               'in the data within the range [minHz,maxHz]' 10 '(overrides frequency specified in ''coher'' flag)']  } ...
			   { 'Style', 'text', 'string', 'Percent low-amp. trials to ignore', 'tooltipstring', ['percent of trials to reject for low' ...
			    'amplitude. Else,' 10 'if prct is in the range [-100,0] -> percent to reject for high amplitude'] } ...
			   { 'Style', 'text', 'string', 'Window center (ms)', 'tooltipstring', 'Center time of the n-cycle window'  } ...
			   { 'Style', 'text', 'string', 'Wavelet cycles', 'tooltipstring', 'cycles per wavelet window'  } {}...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.phasesort(3)),num2str(opt.phasesort(3:4)),'') 'tag', 'phase', 'callback', commandphase } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.phasesort(2)),num2str(opt.phasesort(2)),''), 'tag', 'phase2' } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.phasesort(1)),num2str(opt.phasesort(1)),''), 'tag', 'phase3' } ...
			   { 'Style', 'text', 'string', '        3'  } {}...
			   {} ...
			   { 'Style', 'text', 'string', 'Inter-trial coherence options', 'fontweight', 'bold'} ...
			   { 'Style', 'text', 'string', 'Frequency (Hz | minHz maxHz)', 'tooltipstring', [ '[freq] -> plot erp plus amp & coher at freq (Hz)' 10 ...
               '[minHz maxHz] -> find max in frequency range' 10 '(or at phase freq above, if specified)']} ...
			   { 'Style', 'text', 'string', 'Signif. level (<0.20)', 'tooltipstring', 'add coher. signif. level line at alpha (alpha range: (0,0.1])' } ...
			   { 'Style', 'text', 'string', 'Amplitude limits (dB)'  } ...
			   { 'Style', 'text', 'string', 'Coher limits (<=1)'  } ...
			   { 'Style', 'checkbox', 'string', 'Image amps', 'tooltipstring',  context('plotamps',vars,txt), 'value', fastif(strcmpi(opt.plotamps, 'on'), 1,0), 'tag', 'plotamps' } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.coher(1)), num2str(opt.coher(1:2)), ''), 'tag', 'coher', 'callback', commandcoher } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.coher(3)), num2str(opt.coher(3)),   ''), 'tag', 'coher2'  } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.limits(5)), num2str(opt.limits(5:6)), ''), 'tag', 'limamp' } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.limits(7)), num2str(opt.limits(7:8)), ''), 'tag', 'limcoher' } ...
               {'style', 'text', 'string', '   (Requires signif.)' } ...
			   {} ...
			   { 'Style', 'text', 'string', 'Other options', 'fontweight', 'bold'} ...
			   { 'Style', 'text', 'string', 'Plot spectrum (minHz maxHz)','tooltipstring',  context('spec',vars,txt)} ...
			   { 'Style', 'text', 'string', 'Baseline ampl. (dB)', 'tooltipstring', 'Use it to fix baseline amplitude' } ...
			   { 'Style', 'text', 'string', 'Mark times (ms)','tooltipstring',  context('vert',vars,txt)} ...
			   { 'Style', 'text', 'string', 'More options (see >> help erpimage)' } ...
			   { 'Style', 'edit', 'string', num2str(opt.spec), 'tag', 'spec' } ...
			   { 'Style', 'edit', 'string', fastif(~isnan(opt.limits(9)), num2str(opt.limits(9)), ''), 'tag', 'limbaseamp' } ...
			   { 'Style', 'edit', 'string', num2str(opt.vert), 'tag', 'vert' } ...
			   { 'Style', 'edit', 'string', '', 'tag', 'others' } ...
			};
	if typeplot == 0 % add extra param for components
		geometry = { [1 1 0.1 0.8 2.1] geometry{:} };
		uilist   = { { } { } { } { } { } uilist{:}};
		uilist{1} = uilist{6};
		uilist{2} = uilist{7};
		uilist{6} = { 'Style', 'text', 'string', 'Project to channel #', 'fontweight', 'bold','tooltipstring', ['Project component(s) to data channel' 10 ...
												  'This allows plotting projected component activity at one channel in microvolts'] };
		uilist{7} = { 'Style', 'edit', 'string', getkeyval(lastcom, 4), 'tag', 'projchan' };
	end
    [oldres a b res] = inputgui( 'geometry', geometry, 'uilist', uilist, 'helpcom', 'pophelp(''pop_erpimage'');', ...
							 'title', fastif( typeplot, 'Channel ERP image -- pop_erpimage()', 'Component ERP image -- pop_erpimage()'), 'userdata', EEG);
	if isempty(oldres), return; end

	% first rows
	% ---------
    channel = eeg_decodechan(EEG.chanlocs, res.chan);
	titleplot    = res.title;
	if isfield(res, 'projchan'),
        if ~isempty(res.projchan)
            if strcmpi(res.projchan(1),'''')
                 projchan = eval( [ '{' res.projchan '}' ]);
            else projchan = parsetxt( res.projchan);
            end
            if ~isempty(projchan) && ~isempty(str2num(projchan{1}))
                projchan = cellfun(@str2num, projchan);
            end
        else
            projchan = [];
        end
    else,
        projchan = [];
    end
    opt = [];
	if ~isempty(res.others)
        try,
            tmpcell = eval( [ '{' res.others '}' ] );
            opt = struct( tmpcell{:} );
        catch, error('Additional options ("More options") requires ''key'', ''val'' arguments');
        end
	end
	if ~typeplot && isempty(projchan)
        opt.yerplabel = '';
    else
        opt.yerplabel = '\muV' ;
	end
	smooth       = eval(res.smooth);
    if res.plotmap
		if isfield(EEG.chanlocs, 'theta')
            if ~isfield(EEG, 'chaninfo'), EEG.chaninfo = []; end
			if typeplot == 0
				     opt.topo = [ ' { mean(EEG.icawinv(:,[' int2str(channel) ']),2) EEG.chanlocs EEG.chaninfo } '];
			else     opt.topo = [ ' { [' int2str(channel) '] EEG.chanlocs EEG.chaninfo } '];
			end;
		end
	end

	decimate     = eval( res.decimate );
	if res.erp
		opt.erp = 'on';
	end

	% finding limits
	% --------------
	limits(1:8)  = NaN;
	if ~isempty(res.limerp)
		limits(3:4) = eval( [ '[' res.limerp ']' ]);
	end
	if ~isempty(res.limtime) % time limits
		if ~strcmp(res.limtime, num2str(1000*[EEG.xmin EEG.xmax]))
			limits(1:2) = eval( [ '[' res.limtime ']' ]);
		end
	end
	if ~isempty(res.limamp)
		limits(5:6) = eval( [ '[' res.limamp ']' ]);
	end
	if ~isempty(res.limcoher)
		limits(7:8) = eval( [ '[' res.limcoher ']' ]);
	end
	if ~isempty(res.limbaseamp)
		limits(9) = eval( res.limbaseamp ); %bamp
	end
	if ~all(isnan(limits))
        opt.limits = limits;
	end

	% color limits
	% --------------
	if res.cbar
		opt.cbar = 'on';
	end
	if res.caxis
		opt.caxis = str2num(res.caxis);
	end

	% event rows
	% ----------
	if res.nosort
		opt.nosort = 'on';
	end
	try, sortingeventfield = eval( res.field ); catch, sortingeventfield = res.field; end
    if ~isempty(res.type)
       if strcmpi(res.type(1),'''')
            sortingtype = eval( [ '{' res.type '}' ] );
       else sortingtype = parsetxt( res.type );
       end
    end
	sortingwin   = eval( [ '[' res.eventrange ']' ] );
	if ~isempty(res.field) && ~strcmp(res.renorm, 'no')
		opt.renorm = res.renorm;
	end
	if ~isempty(res.align)
		opt.align = str2num(res.align);
	end
	if res.noplot
		opt.noplot = 'on';
	end

	% phase rows
	% ----------
	tmpphase = [];
	if ~isempty(res.phase)
		tmpphase = eval( [ '[ 0 0 ' res.phase ']' ]);
	end
	if ~isempty(res.phase2)
		tmpphase(2) = eval( res.phase2 );
	end
	if ~isempty(res.phase3)
		tmpphase(1) = eval( res.phase3 );
	end
	if ~isempty(tmpphase)
		opt.phasesort = tmpphase;
	end

	% coher row
	% ----------
	tmpcoher = [];
	if res.plotamps
		opt.plotamps = 'on';
	end
	if ~isempty(res.coher)
		tmpcoher = eval( [ '[' res.coher ']' ]);
	end
	if ~isempty(res.coher2)
		if length(tmpcoher) == 1
			tmpcoher(2) = tmpcoher(1);
		end
		tmpcoher(3) = eval( res.coher2 );
	end
	if ~isempty(tmpcoher)
		opt.coher = tmpcoher;
	end

	% options row
	% ------------
	if ~isempty(res.spec)
		opt.spec = eval( [ '[' res.spec ']' ]);
	end
	if ~isempty(res.vert)
		opt.vert = eval( [ '[' res.vert ']' ]);
	end
	figure;
    options = '';
else
	options = '';
	if nargin < 4
		projchan = [];
	end
	if nargin < 5
		titleplot = '';
	end
	if nargin < 6
		smooth = 5;
	end
	if nargin < 7
		decimate = 0;
	end
	if nargin < 8
		sortingtype = [];
	end
	if nargin < 9
		sortingwin = [];
	end
	if nargin < 10
		sortingeventfield = [];
	end
    %options = vararg2str(varargin); % NO BECAUSE OF THE CHANNEL LOCATION
    %                                  PROBLEM BELOW
	for i=1:length( varargin )
		if ischar( varargin{ i } )
			options = [ options ', ''' varargin{i} '''' ];
		else
		  if ~iscell( varargin{ i } )
		      options = [ options ',' vararg2str({varargin{i}}) ];
		  else
		      %options = [ options ', { [' num2str(varargin{ i }{1}') ']'' EEG.chanlocs EEG.chaninfo }' ]; % JRI -- why does this ignore value passed as topo option?
        if length(varargin{i})>1
		optchanlocs = varargin{i}{2}; % JRI -- fix
        else
		optchanlocs = EEG.chanlocs;
	end;
  	if length(varargin{i})>2,
            optchaninfo = varargin{i}{3};
        else
            optchaninfo = EEG.chaninfo;
        end
          options = [ options ', { [' num2str(varargin{ i }{1}') ']'' optchanlocs optchaninfo }' ];
		  end;
		end
	end;
end
try, icadefs; set(gcf, 'color', BACKCOLOR,'Name',' erpimage()'); catch, end

% testing inputs
% --------------
if ischar(channel)
    channel = eeg_decodechan(EEG.chanlocs, channel);
end
if typeplot == 0 && length(channel) > 1 && isempty(projchan)
	error('A channel must be selected to plot (the sum of) several component projections');
end

% find sorting latencies
% ---------------------
typetxt = '';
if ~isempty(sortingeventfield)
    %events = eeg_getepochevent( EEG, sortingtype, sortingwin, sortingeventfield);
	events = sprintf('eeg_getepochevent( EEG, %s)', vararg2str({sortingtype, sortingwin, sortingeventfield}));

    % generate text for the command
    % -----------------------------
    for index = 1:length(sortingtype)
        if ischar(sortingtype{index})
            typetxt = [typetxt ' ''' sortingtype{index} '''' ];
        else
            typetxt = [typetxt ' ' num2str(sortingtype{index}) ];
        end
    end;
% $$$ 	% renormalize latencies if necessary
% $$$ 	% ----------------------------------
% $$$ 	switch lower(renorm)
% $$$ 	    case 'yes',
% $$$ 	         disp('Pop_erpimage warning: *** sorting variable renormalized ***');
% $$$ 	         events = (events-min(events)) / (max(events) - min(events)) * ...
% $$$ 	                        0.5 * (EEG.xmax*1000 - EEG.xmin*1000) + EEG.xmin*1000 + 0.4*(EEG.xmax*1000 - EEG.xmin*1000);
% $$$ 	    case 'no',;
% $$$ 	    otherwise,
% $$$ 	        locx = findstr('x', lower(renorm))
% $$$ 	        if length(locx) ~= 1, error('Pop_erpimage error: unrecognize renormalazing formula'); end
% $$$ 	        eval( [ 'events =' renorm(1:locx-1) 'events' renorm(locx+1:end) ';'] );
% $$$ 	end
else
	events = 'ones(1, EEG.trials)*EEG.xmax*1000';
    %events = ones(1, EEG.trials)*EEG.xmax*1000;
    sortingeventfield = '';
end;

if ischar(projchan)
    projchan = { projchan };
end
if iscell(projchan)
    projchannum = std_chaninds(EEG, projchan);
else
    projchannum = projchan;
end

if typeplot == 1
	tmpsig = ['mean(EEG.data([' int2str(channel) '], :),1)'];
else
    % test if ICA was computed or if one has to compute on line
    % ---------------------------------------------------------
    tmpsig = [ 'eeg_getdatact(EEG, ''component'', [' int2str(channel) '], ''projchan'', [' int2str(projchannum) '])' ];
end

% outputs
% -------
outstr = '';
if ~popup
    for io = 1:nargout, outstr = [outstr 'varargout{' int2str(io) '},' ]; end
    if ~isempty(outstr), outstr = [ '[' outstr(1:end-1) '] =' ]; end
end

% plot title
% ----------
if isempty(titleplot)
    if typeplot==1 % if channel plot
        if ~isempty(EEG.chanlocs) % if channel information exist
              titleplot = [ EEG.chanlocs(channel).labels ];
        else, titleplot = [ int2str(channel) ];
        end
    else
        titleplot = [ 'Comp. ' int2str(channel) ];
        if ~isempty(projchan),
            tmpstr = vararg2str({projchan});
            tmpstr(find(tmpstr == '''')) = '"';
            titleplot = [ titleplot ' -> Chan. ' tmpstr ];
        end
    end
end

% plot the data and generate output command
% --------------------------------------------
if isempty( options )
    if isfield(opt, 'topo')
        tmptopo = opt.topo;
        opt = rmfield(opt, 'topo');
    else
        tmptopo = '';
    end
    if ~isempty(opt)
        fields = fieldnames(opt);
        values = struct2cell(opt);
        params = { fields{:}; values{:} };
        options = [ ',' vararg2str( { params{:} } ) ];
        tmpind = find( options == '\' ); options(tmpind(1:2:end)) = [];
        if ~isempty(tmptopo), options = [ options ',''topo'',' tmptopo ]; end
    end
end

% varargout{1} = sprintf('figure; pop_erpimage(%s,%d,%d,''%s'',%d,%d,{%s},[%s],''%s'',''%s''%s);', inputname(1), typeplot, channel, titleplot, smooth, decimate, typetxt, int2str(sortingwin), sortingeventfield, renorm, options);
popcom = sprintf('figure; pop_erpimage(EEG,%d, [%s],[%s],''%s'',%d,%d,{%s},[%s],''%s'' %s);', typeplot, int2str(channel), vararg2str({projchan}), titleplot, smooth, decimate, typetxt, int2str(sortingwin), sortingeventfield, options);

com = sprintf('%s erpimage( %s, %s, linspace(EEG.xmin*1000, EEG.xmax*1000, EEG.pnts), ''%s'', %d, %d %s);', outstr, tmpsig, events, titleplot, smooth, decimate, options);
disp('Command executed by pop_erpimage:');
disp(' '); disp(com); disp(' ');
eval(com)

if popup
	varargout{1} = popcom; % [10 '% Call: ' com];
end

return;

% get contextual help
% -------------------
function txt = context(var, allvars, alltext);
	loc = strmatch( var, allvars);
	if ~isempty(loc)
		txt= alltext{loc(1)};
	else
		disp([ 'warning: variable ''' var ''' not found']);
		txt = '';
	end


function y = eq(X,Y)
%EQ (overloaded)

if isa(X,'blkvar')
    X = sdpvar(X);
end

if isa(Y,'blkvar')
    Y = sdpvar(Y);
end

try
    y = constraint(X,'==',Y);
catch
    error(lasterr)
end


function net = append_blocks(net, method, objectivetype, errortype, imchs)
% APPEND_BLOCKS function adds necessary blocks to the CNN.
%
%   NET = append_blocks(NET, METHOD, OBJECTIVE, ERROR, IMCHANNELS)
%
%   METHOD is a string that can contain one of the pooling strings:
%     'mac'   - global max pooling layer
%     'spoc'  - global average pooling layer
%     'gem'   - global generalized mean pooling layer with one p for all conv filters
%     'gemmp' - global generalized mean pooling layer with multiple p for each conv filter
%	If METHOD contains string 'edgefilter', the network will be pre-pended with the EdgeFilter layer.
%
%   OBJECTIVE & ERROR are a cell array with 2 values:
%     {'contrastiveloss', M} - contrastive loss with margin M
%     {'tripletloss', M}     - triplet loss with margin M
%     {'batchmap'}           - mean average precision for all queries in a batch
%
%   IMCHANNELS is a number of image channels that will be used for training, ie. 1 or 3.
%     If IMCHANNELS == 1 channels of first conv layers are aggregated using average pooling.
%
% Authors: F. Radenovic, G. Tolias, O. Chum. 2017.

	import dagnn.*;

	if ~exist('imchs'), imchs = 3; end
	if imchs == 1 	% sum aggregate first conv layer, if 1 input channel
		net.params(1).value = sum(net.params(1).value,3);
		net.layers(1).block.size(3) = 1;
	end
	method = lower(method);

	% Edge filtering layer
	if strfind(method, 'edgefilter')
		inputs = {'input'};
		outputs = {'x0'};
		params = struct('name', {}, 'value', {}, 'learningRate', [], 'weightDecay', []);
		name = 'edgelayer';
		block = EdgeFilter();

		params(1).name  = 'edgelayer_w'; params(1).value = single(10);
		params(2).name  = 'edgelayer_p'; params(2).value = single(0.5);
		params(3).name  = 'edgelayer_s'; params(3).value = single(500);
		params(4).name  = 'edgelayer_t'; params(4).value = single(0.1);

		net.addLayer(name, block, inputs, outputs, {params.name});

		% edgelayer_w params.value
		i = 1; f = net.getParamIndex(params(i).name);
		net.params(f).value = params(i).value; net.params(f).learningRate = 0; net.params(f).weightDecay = 0;
		% edgelayer_p params.value
		i = 2; f = net.getParamIndex(params(i).name);
		net.params(f).value = params(i).value; net.params(f).learningRate = 1; net.params(f).weightDecay = 0;
		% edgelayer_s params.value
		i = 3; f = net.getParamIndex(params(i).name);
		net.params(f).value = params(i).value; net.params(f).learningRate = 0; net.params(f).weightDecay = 0;
		% edgelayer_t params.value
		i = 4; f = net.getParamIndex(params(i).name);
		net.params(f).value = params(i).value; net.params(f).learningRate = 0.1; net.params(f).weightDecay = 0;

		net.layers(1).inputs{1} = outputs{1};
	end

	l = 0;

	% Global pooling layer
	l = l + 1;
	inputs = {sprintf('xx%d',l-1)};
	outputs = {'pooldescriptor'};
	params = struct('name', {}, 'value', {}, 'learningRate', [], 'weightDecay', []);
	name = 'pooldescriptor' ;
	if strfind(method, 'mac')
		block = MAC();
	elseif strfind(method, 'spoc')
		block = SPOC();
	elseif strfind(method, 'gem')
		block = GeM();
		if strfind(method, 'gemmp'), sz = [1 1 D 1]; else, sz = [1 1 1 1]; end
		params(1).name = 'gem';
		params(1).value = ones(sz, 'single') * 3;
		params(1).learningRate = 10;
		params(1).weightDecay  = 0;
	else
		error(sprintf('Unknown method %s\n', method));
	end
	net.addLayer(name, block, inputs, outputs, {params.name});
	if numel(strfind(method, 'gem'))
		findex = net.getParamIndex(params(1).name) ;
		if ~isempty(params(1).value)
			net.params(findex).value = params(1).value ;
			net.params(findex).learningRate = params(1).learningRate;
			net.params(findex).weightDecay = params(1).weightDecay;
		end
	end

	% L2 normalization layer
	inputs = {'pooldescriptor'};
	outputs = {'l2descriptor'};
	params = struct('name', {}, 'value', {}, 'learningRate', [], 'weightDecay', []);
	name = 'l2descriptor';
	block = L2N();
	net.addLayer(name, block, inputs, outputs, {params.name});

    % Objective layer
	inputs{1} = 'l2descriptor';
	inputs{2} = 'label';
	outputs = {'objective'};
	params = struct('name', {}, 'value', {}, 'learningRate', [], 'weightDecay', []);
	name = 'objective';
	switch objectivetype{1}
		case 'contrastiveloss'
			block = ContrastiveLoss('margin', objectivetype{2});
		case 'tripletloss'
			block = TripletLoss('margin', objectivetype{2});
		otherwise
			ferror('Unknow loss type\n');
	end
	net.addLayer(name, block, inputs, outputs, {params.name});

    % Error layer
	if exist('errortype') & numel(errortype)
		inputs{1} = 'l2descriptor';
		inputs{2} = 'label';
		outputs = {'error'};
		params = struct('name', {}, 'value', {}, 'learningRate', [], 'weightDecay', []);
		name = 'error';
		switch errortype{1}
			case 'contrastiveloss'
				block = ContrastiveLoss('margin', objectivetype{2});
			case 'tripletloss'
				block = TripletLoss('margin', objectivetype{2});
			case 'batchmap'
				block = BatchMAP();
			otherwise
				ferror('Unknow error type\n');
		end
		net.addLayer(name, block, inputs, outputs, {params.name});
	end


function []=anim8_DIC_3D_pairs_faceMeasure_direction(DIC3DAllPairsResults,faceMeasureString,varargin)
%% function for plotting 3D-DIC results of face measures as color + direction as arrows in STEP3.
% plotting 3D surfaces from camera pairs, animation changing
% with time, and the faces colored according to faceMeasureString
% this function is called in plotMultiDICPairResults
%
% Options:
% anim8_DIC_3D_pairs_faceMeasure(DIC_3Dallpairs_results,faceMeasureString)
% anim8_DIC_3D_pairs_faceMeasure(DIC_3Dallpairs_results,faceMeasureString,optStruct)
%
% Inputs:
% * DIC3DAllPairsResults
% * faceMeasureString: can be any of the following:
%   'Epc1','Epc2','epc1','epc2','Lamda1','Lamda2', or a combination of two  in a cell array to plot side by side
% * optStruct: optional structure for plotting options which may include any of the following fields:
%   - smoothLogic: logical variable for smoothing (true)/not smoothing (false) the face measure
%   - FaceAlpha: transparacy of the faces (scalar between 0 and 1, where zero is transparent and 1 is opaque)
%   - colorBarLimits: a 2x1 scalar vector for the colobar limits. if not set, it's automatic
%   - dataLimits: a 2x1 scalar vector for the data limits of the face measure. if a face measure is outside these limits, it is set to NaN. if not set no face is set to NaN
%   - colorMap
%   - zDirection: 1 for z up and -1 for z down
%   - lineColor: line color for the mesh. can be for example 'b','k','none',etc...
%   - supTitleString=faceMeasureString;

%% Assign plot options
Narg=numel(varargin);
switch Narg
    case 1
        optStruct=varargin{1};
    case 0
        optStruct=struct;
    otherwise
        ('wrong number of input arguments');
end

% complete the struct fields
if ~isfield(optStruct,'smoothLogic')
    optStruct.smoothLogic=0;
end
if ~isfield(optStruct,'FaceAlpha')
    optStruct.FaceAlpha=1;
end
if ~isfield(optStruct,'dataLimits')
    optStruct.dataLimits=[-inf inf];
end
if ~isfield(optStruct,'zDirection') % 1 or -1
    optStruct.zDirection=1;
end
if ~isfield(optStruct,'lineColor') % 'none' or 'k'
    optStruct.lineColor='none';
end
if ~isfield(optStruct,'maxCorrCoeff')
    optStruct.maxCorrCoeff=[];
end

%%
nFrames=numel(DIC3DAllPairsResults{1}.Points3D);

quiverScaleFactor=20;

DIC_3Djoined_results=joinPairs(DIC3DAllPairsResults);
[xl,yl,zl]=axesLimits(DIC_3Djoined_results.Points3D);

%% Assign the right face measure into FC

if iscell(faceMeasureString)
    faceMeasureCell=faceMeasureString;
    nStrains=numel(faceMeasureString);
    switch nStrains
        case 1
            FC=cell(nFrames,nStrains);
            D=cell(nFrames,nStrains);
            Ds=cell(nFrames,nStrains);
            Vc=cell(nFrames,nStrains);
        case 2
            FC=cell(nFrames,nStrains);
            D=cell(nFrames,nStrains);
            Ds=cell(nFrames,nStrains);
            Vc=cell(nFrames,nStrains);
        otherwise
            error('wrong number of cells in faceMeasureString cell array (must be 1 or 2)');
    end
elseif ischar(faceMeasureString)
    nStrains=1;
    faceMeasureCell=cell(1);
    faceMeasureCell{1}=faceMeasureString;
    FC=cell(nFrames,1);
    D=cell(nFrames,1);
    Ds=cell(nFrames,1);
    Vc=cell(nFrames,1);
else
    error('wrong face measure (second input variable)');
end

if ~isfield(optStruct,'supTitleString') % 'none' or 'k'
    optStruct.supTitleString=faceMeasureCell;
end

directionStringCell=cell(nStrains,1);
for is=1:nStrains
    switch faceMeasureCell{is}
        case 'Epc1'
            directionStringCell{is}='Epc1vecCur';
        case 'Epc2'
            directionStringCell{is}='Epc2vecCur';
        case 'epc1'
            directionStringCell{is}='epc1vec';
        case 'epc2'
            directionStringCell{is}='epc2vec';
        case 'Lamda1'
            directionStringCell{is}='Epc1vecCur';
        case 'Lamda2'
            directionStringCell{is}='Epc2vecCur';
        otherwise
            error('unexpected face measure string. plots not created');
    end
    for it=1:nFrames
        FC{it,is}=DIC_3Djoined_results.Deform.(faceMeasureCell{is}){it}; % face color (strain)
        D{it,is}=DIC_3Djoined_results.Deform.(directionStringCell{is}){it}; % direction (unit vector)
        Vc{it,is}=DIC_3Djoined_results.FaceCentroids{it};
        if ~isempty(optStruct.maxCorrCoeff)
            corrNow=DIC_3Djoined_results.FaceCorrComb{it};
            FC{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
            D{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
            Vc{it,is}(corrNow>optStruct.maxCorrCoeff,:)=NaN;
        end
        switch faceMeasureCell{is}
            case {'Epc1','Epc2','epc1','epc2'}
                Ds{it,is}=quiverScaleFactor*FC{it,is}.*D{it,is}; % direction with magnitude (scaled vector)
            case {'Lamda1','Lamda2'}
                Ds{it,is}=quiverScaleFactor*(FC{it,is}-1).*D{it,is}; % direction with magnitude (scaled vector)
        end

    end
end
FCmat = cell2mat(FC);
if ~isfield(optStruct,'colorBarLimits')
    switch faceMeasureCell{is}
        case {'Epc1','Epc2','epc1','epc2'}
            optStruct.colorBarLimits=[-prctile(abs(FCmat(:)),100) prctile(abs(FCmat(:)),100)];
        case {'Lamda1','Lamda2'}
            optStruct.colorBarLimits=[1-prctile(abs(FCmat(:)-1),100) 1+prctile(abs(FCmat(:)-1),100)];
    end
end
colorBarLogic=1;
if ~isfield(optStruct,'colorMap')
    optStruct.colorMap=.8*coldwarm;
end

%% Plot

animStruct=struct;

hf=cFigure;
hf.Units='normalized'; hf.OuterPosition=[.05 .05 .9 .9]; hf.Units='pixels';

for is=1:nStrains
    subplot(1,nStrains,is);

    axisGeom;
    ax=gca;
    ax.CameraUpVector=[0 0 optStruct.zDirection];
    colormap(optStruct.colorMap);
    if colorBarLogic
        colorbar;
        caxis(optStruct.colorBarLimits);
    end

    title(optStruct.supTitleString{is});
    axis off
    % camlight headlight

    it=1;
    Fnow=DIC_3Djoined_results.Faces;
    Pnow=DIC_3Djoined_results.Points3D{it};
    Vnow=Vc{it,is};
    FCnow=FC{it,is};
    Dnow=Ds{it,is};
    if optStruct.smoothLogic
        [FCnow]=triSmoothFaceMeasure(FCnow,Fnow,Pnow,[],[]);
    end
    FCnow(FCnow<optStruct.dataLimits(1))=NaN;
    FCnow(FCnow>optStruct.dataLimits(2))=NaN;

    hp(is)=gpatch(Fnow,Pnow,FCnow,optStruct.lineColor,optStruct.FaceAlpha); hold on
    hq(is)=quiver3(Vnow(:,1),Vnow(:,2),Vnow(:,3),Dnow(:,1),Dnow(:,2),Dnow(:,3),0,'Color',.2*[1 1 1],'ShowArrowHead','off','AutoScale','on'); hold on;
%
    h_ax=gca;
    h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

end

%% fill in the animstruct

animStruct.Time=1:nFrames;
animStruct.Handles=cell(1,nFrames);
animStruct.Props=cell(1,nFrames);
animStruct.Set=cell(1,nFrames);

for it=1:nFrames
    animStruct.Handles{it}=[];
    animStruct.Props{it}=cell(1,8*nStrains);
    animStruct.Set{it}=cell(1,8*nStrains);
    Pnow=DIC_3Djoined_results.Points3D{it};

    for is=1:nStrains
        FCnow=FC{it,is};
        if optStruct.smoothLogic
            [FCnow]=triSmoothFaceMeasure(FCnow,Fnow,Pnow,[],[]);
        end
        FCnow(FCnow<optStruct.dataLimits(1))=NaN;
        FCnow(FCnow>optStruct.dataLimits(2))=NaN;

        Fnow=DIC_3Djoined_results.Faces;
        Pnow=DIC_3Djoined_results.Points3D{it};
        Vnow=Vc{it,is};
        Dnow=Ds{it,is};

        animStruct.Handles{it}=[animStruct.Handles{it} hp(is) hp(is) hq(is) hq(is) hq(is) hq(is) hq(is) hq(is)]; %Handles of objects to animate (add one every pair)

        animStruct.Props{it}{1+8*(is-1)}='CData';
        animStruct.Props{it}{2+8*(is-1)}='Vertices'; %Properties of objects to animate
        animStruct.Props{it}{3+8*(is-1)}='XData'; %Properties of objects to animate
        animStruct.Props{it}{4+8*(is-1)}='YData'; %Properties of objects to animate
        animStruct.Props{it}{5+8*(is-1)}='ZData'; %Properties of objects to animate
        animStruct.Props{it}{6+8*(is-1)}='UData'; %Properties of objects to animate
        animStruct.Props{it}{7+8*(is-1)}='VData'; %Properties of objects to animate
        animStruct.Props{it}{8+8*(is-1)}='WData'; %Properties of objects to animate

        animStruct.Set{it}{1+8*(is-1)}=FCnow;
        animStruct.Set{it}{2+8*(is-1)}=Pnow; %Property values for to set in order to animate
        animStruct.Set{it}{3+8*(is-1)}=Vnow(:,1); %Property values for to set in order to animate
        animStruct.Set{it}{4+8*(is-1)}=Vnow(:,2); %Property values for to set in order to animate
        animStruct.Set{it}{5+8*(is-1)}=Vnow(:,3); %Property values for to set in order to animate
        animStruct.Set{it}{6+8*(is-1)}=Dnow(:,1); %Property values for to set in order to animate
        animStruct.Set{it}{7+8*(is-1)}=Dnow(:,2); %Property values for to set in order to animate
        animStruct.Set{it}{8+8*(is-1)}=Dnow(:,3); %Property values for to set in order to animate

        h_ax.XLim = xl; h_ax.YLim = yl; h_ax.ZLim = zl;

    end
end

anim8(hf,animStruct);

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function example_sel2html(fn)
%Convert Dick Benson's example_sel text files to HTML documents

if nargin < 1
    fn = 'example_sel.txt';
end
f = textread(fn,'%s','delimiter','\n','whitespace','');

ln = [];
for n = 1:length(f)
    [st1,fn1,tk1] = regexp(f{n},'^([^\$]*)');
    [st2,fn2,tk2] = regexp(f{n},'\$(.*)$');
    % Blank line.  Also, ignore initialization lines (#)
    if isempty(tk1) | (strncmp(f{n},'#',1) & length(f{n})>1)
        ln(n).text = '';
        ln(n).code = '';
        ln(n).style = '';
    else
        ln(n).text = deblank(f{n}(tk1{1}(1):tk1{1}(2)));
        ln(n).text = strrep(ln(n).text,'>','>');
        ln(n).text = strrep(ln(n).text,'<','<');

        % Determine the indent depending on how many spaces there are
        [st,fn] = regexp(ln(n).text,'^([\s]*)');
        if isempty(fn)
            ln(n).style = 'level1';
        elseif fn<=4
            ln(n).style = 'level2"';
        else
            ln(n).style = 'level3"';
        end

        if ~isempty(tk2)
            ln(n).code = f{n}(tk2{1}(1):tk2{1}(2));
        else
            ln(n).code = '';
        end

    end

    %Look for initialization commands:  Line starts with #
    if strncmp(f{n},'#',1) & length(f{n})>1
        evalin('base',f{n}(2:end),'disp([''fail to execute string: '',f{n}(2:end)])');
        disp('Evaluating Initialization commands');
    end;

end

s{1} = '';
s{end+1} = '<title>Model Based Design and the Path to FPGAs</title>';
s{end+1} = '';
s{end+1} = '';
s{end+1} = '';

for n = 1:length(ln)
    if isempty(ln(n).code)
        if isempty(ln(n).text)
            % No text, no code
            s{end+1} = '
';
        else
            % Text, no code
            s{end+1} = sprintf('
%s
', ...
                ln(n).style,ln(n).text);
        end
    else
        % Text and code
        s{end+1} = sprintf('
%s
', ...
            ln(n).style,ln(n).code,ln(n).text);
    end
end
s{end+1} = '';

web(['text://' s{:}]);

github-repos/MATLAB/Sable-mcbench-benchmarks/mcbench-benchmarks-ba13b2f0296ef49491b95e3f984c7c41fccdb6d8/9565-model-based-design-and-fpga-implementation-with-simulink/Model Based Design and the FPGA Implementation in Simulink/edge_detection_menu.m


function [incorrectRxns,incorrectMets] = validateCompartments(model)
% This function checks if there are any reactions with incorrect
% compartments in the refined reconstructions. Appropriate compartments
% include [c], [e], and [p].
%
% USAGE:
%
%    [incorrectRxns,incorrectMets] = validateCompartments(model)
%
% INPUTS
% model             COBRA model structure
%
% OUTPUTS
%
% incorrectRxns     Reactions including metabolites in inappropriate compartments
% incorrectMets     Metabolites located in inappropriate compartments
%
% AUTHOR:
%   Almut Heinken, 10/2020

findIncorrectMets = find(~contains(model.mets,{'[c]','[e]','[p]'}));
if ~isempty(findIncorrectMets)
    incorrectMets = model.mets(findIncorrectMets);
    incorrectRxns = {};

    for i=1:length(incorrectMets)
        [Rxns]=findRxnsFromMets(model,incorrectMets{i});
        incorrectRxns=union(incorrectRxns,Rxns);
    end

else
    incorrectMets = {};
    incorrectRxns = {};
end

end


function mode = addReservedColors(mode)
%
% mode = addReservedColors(mode)
%
% Adds reserved colors to a displayMode and its underlying colormap.
%
% djh 1/98

mode.white=256;
mode.cmap(256,:) = [1,1,1]; 		% white

mode.black=255;
mode.cmap(255,:) = [0,0,0]; 		% black

mode.red=254;
mode.cmap(254,:) = [1,0,0]; 		% red

mode.green=253;
mode.cmap(253,:) = [0,1,0]; 		% green

mode.blue=252;
mode.cmap(252,:) = [0,0,1]; 		% blue

mode.cyan=251;
mode.cmap(251,:) = [0,1,1]; 		% cyan

mode.magenta=250;
mode.cmap(250,:) = [1,0,1]; 		% magenta

mode.yellow=249;
mode.cmap(249,:) = [1,1,0]; 		% yellow


classdef (Abstract) Base < matlabshared.libiio.base & ...
        matlab.system.mixin.CustomIcon
    %AD9680 Base Class

    properties (Nontunable)
        %SamplesPerFrame Samples Per Frame
        %   Number of samples per frame, specified as an even positive
        %   integer from 2 to 16,777,216. Using values less than 3660 can
        %   yield poor performance.
        SamplesPerFrame = 2^15;
    end

    properties(Nontunable, Hidden)
        Timeout = Inf;
        kernelBuffersCount = 2;
        dataTypeStr = 'int16';
    end

    properties (Abstract, Hidden, Constant)
       Type
    end

    properties (Hidden, Constant)
        ComplexData = false;
    end

    methods
        %% Constructor
        function obj = Base(varargin)
            % Returns the matlabshared.libiio.base object
            coder.allowpcode('plain');
            obj = obj@matlabshared.libiio.base(varargin{:});
        end
        % Check SamplesPerFrame
        function set.SamplesPerFrame(obj, value)
            validateattributes( value, { 'double','single' }, ...
                { 'real', 'positive','scalar', 'finite', 'nonnan', 'nonempty','integer','>',0,'<',2^20+1}, ...
                '', 'SamplesPerFrame');
            obj.SamplesPerFrame = value;
        end
    end

    %% API Functions
    methods (Hidden, Access = protected)

        function icon = getIconImpl(obj)
            icon = sprintf(['AD9680 ',obj.Type]);
        end

        function setupInit(~)
            % Unused
        end

    end

    %% External Dependency Methods
    methods (Hidden, Static)

        function tf = isSupportedContext(bldCfg)
            tf = matlabshared.libiio.ExternalDependency.isSupportedContext(bldCfg);
        end

        function updateBuildInfo(buildInfo, bldCfg)
            % Call the matlabshared.libiio.method first
            matlabshared.libiio.ExternalDependency.updateBuildInfo(buildInfo, bldCfg);
        end

        function bName = getDescriptiveName(~)
            bName = 'AD9680';
        end

    end
end


function hmObj = hlp_validateHeadModelObject(hmObj)
% helper function to check the head model object, and
% load from base workspace if necessary
% Author: Tim Mullen, SCCN/INC/UCSD 2013

if isempty(hmObj)
    hmObj = 'hmObj'; % default name of variable in base wkspace
end
if ischar(hmObj)
    % load variable from base workspace
    try
       hmObj = evalin('base',hmObj);
    catch err1
        % try to open it as a file names
        try
            if ~exist(hmObj,'file'), hmObj = env_translatepath(hmObj); end
            hmObj = hlp_microcache('headmodels',@headModel.loadFromFile,hmObj);
        catch err2
            disp_once('BCILAB:HeadmodelMissing',['Note: The head model named "' hmObj '" was neither found in the base workspace nor could it be loaded as a file.']);
            hmObj = '';
            return;
        end
    end
end

% check that the object is a valid head model object
if ~isobject(hmObj)
    warning('You did not supply a valid head model object');
    hmObj = '';
    return;
end
if ~isprop(hmObj,'leadFieldFile') || isempty(hmObj.leadFieldFile)
    warning('Head model object does not appear to be valid. The lead field matrix does not exist.');
    hmObj = '';
    return;
end


function pot = cg_mom_to_can(pot)
% CG_MOM_TO_CAN Convert a CG potential from moment to canonical form, if necessary.
% pot = cg_mom_to_can(pot)

if pot.subtype ~= 'c'
  for i=1:pot.dsize
    pot.can{i} = mpot_to_cpot(pot.mom{i});
  end
  pot.subtype = 'c';
end


%  Return time frame of a NIFTI dataset. Support both *.nii and
%  *.hdr/*.img file extension. If file extension is not provided,
%  *.hdr/*.img will be used as default.
%
%  It is a lightweighted "load_nii_hdr", and is equivalent to
%  hdr.dime.dim(5)
%
%  Usage: [ total_scan ] = get_nii_frame(filename)
%
%  filename - NIFTI file name.
%
%  Returned values:
%
%  total_scan - total number of image scans for the time frame
%
%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
%
%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
%
function [ total_scan ] = get_nii_frame(fileprefix)

   if ~exist('fileprefix','var'),
      error('Usage: [ hdr, fileprefix, machine ] = get_nii_frame(filename)');
   end

   if ~exist('machine','var'), machine = 'ieee-le'; end

   new_ext = 0;

   if findstr('.nii',fileprefix)
      new_ext = 1;
      fileprefix = strrep(fileprefix,'.nii','');
   end

   if findstr('.hdr',fileprefix)
      fileprefix = strrep(fileprefix,'.hdr','');
   end

   if findstr('.img',fileprefix)
      fileprefix = strrep(fileprefix,'.img','');
   end

   if new_ext
      fn = sprintf('%s.nii',fileprefix);

      if ~exist(fn)
         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
         error(msg);
      end
   else
      fn = sprintf('%s.hdr',fileprefix);

      if ~exist(fn)
         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
         error(msg);
      end
   end

   fid = fopen(fn,'r',machine);

   if fid < 0,
      msg = sprintf('Cannot open file %s.',fn);
      error(msg);
   else
      hdr = read_header(fid);
      fclose(fid);
   end

   if hdr.sizeof_hdr ~= 348
      % first try reading the opposite endian to 'machine'
      switch machine,
      case 'ieee-le', machine = 'ieee-be';
      case 'ieee-be', machine = 'ieee-le';
      end

      fid = fopen(fn,'r',machine);

      if fid < 0,
         msg = sprintf('Cannot open file %s.',fn);
         error(msg);
      else
         hdr = read_header(fid);
         fclose(fid);
      end
   end

   if hdr.sizeof_hdr ~= 348
      % Now throw an error
      msg = sprintf('File "%s" is corrupted.',fn);
      error(msg);
   end

   total_scan = hdr.dim(5);

   return;					% get_nii_frame

%---------------------------------------------------------------------
function [ dsr ] = read_header(fid)

    fseek(fid,0,'bof');
    dsr.sizeof_hdr    = fread(fid,1,'int32')';  % should be 348!

    fseek(fid,40,'bof');
    dsr.dim           = fread(fid,8,'int16')';

    return;					% read_header


function write(obj,filename,create_signature)
%WRITE Write sequence to file.
%   WRITE(seqObj, filename) Write the sequence data to the given
%   filename using the open file format for MR sequences.
%
%   Examples:
%   Write the sequence file to the my_sequences directory
%
%       write(seqObj,'my_sequences/gre.seq')
%
% See also  read

if (nargin<3)
    create_signature=true;
end

fid=fopen(filename, 'w');
assert(fid ~= -1, 'Cannot open file: %s', filename);
fprintf(fid, '# Pulseq sequence file\n');
fprintf(fid, '# Created by MATLAB mr toolbox\n\n');

fprintf(fid, '[VERSION]\n');
fprintf(fid, 'major %s\n', num2str(obj.version_major));
fprintf(fid, 'minor %s\n', num2str(obj.version_minor));
fprintf(fid, 'revision %s\n', num2str(obj.version_revision));
fprintf(fid, '\n');

if ~isempty(obj.definitions)
    fprintf(fid, '[DEFINITIONS]\n');
    keys = obj.definitions.keys;
    values = obj.definitions.values;
    for i=1:length(keys)
        fprintf(fid, '%s ', keys{i});
        if (ischar(values{i}))
            fprintf(fid, '%s ', values{i});
        else
            fprintf(fid, '%.9g ', values{i});
        end
        fprintf(fid, '\n');
    end
	fprintf(fid, '\n');
end

fprintf(fid, '# Format of blocks:\n');
fprintf(fid, '# NUM DUR RF  GX  GY  GZ  ADC  EXT\n');
fprintf(fid, '[BLOCKS]\n');
idFormatWidth = length(num2str(length(obj.blockEvents)));
idFormatStr = ['%' num2str(idFormatWidth) 'd'];
for i = 1:length(obj.blockEvents)
    %fprintf(fid,[idFormatStr ' %2d %2d %3d %3d %3d %2d 0\n'],[i obj.blockEvents(i,:)]);
    %fprintf(fid,[idFormatStr ' %2d %2d %3d %3d %3d %2d 0\n'],[i obj.blockEvents{i}]);
    bd=obj.blockDurations(i)/obj.blockDurationRaster;
    bdr=round(bd);
    assert(abs(bdr-bd)<1e-6); % this may still trigger false alarms for very long delays due to the limited accuracy of the double
    fprintf(fid,[idFormatStr ' %3d %3d %3d %3d %3d %2d %2d\n'], ...
            [i bdr obj.blockEvents{i}(2:end)]);
end
fprintf(fid, '\n');

if ~isempty(obj.rfLibrary.keys)
    fprintf(fid, '# Format of RF events:\n');
    fprintf(fid, '# id amplitude mag_id phase_id time_shape_id delay freq phase\n');
    fprintf(fid, '# ..        Hz   ....     ....          ....    us   Hz   rad\n');
    fprintf(fid, '[RF]\n');
    keys = obj.rfLibrary.keys;
    for k = keys
        libData1 = obj.rfLibrary.data(k).array(1:4);
        libData2 = obj.rfLibrary.data(k).array(6:7);
        delay = round(obj.rfLibrary.data(k).array(5)/obj.rfRasterTime)*obj.rfRasterTime*1e6; % a bit of a hack: round the delay
        fprintf(fid, '%d %12g %d %d %d %g %g %g\n', [k libData1 delay libData2]);
    end
    fprintf(fid, '\n');
end

arbGradMask = obj.gradLibrary.type == 'g';
trapGradMask = obj.gradLibrary.type == 't';

if any(arbGradMask)
    fprintf(fid, '# Format of arbitrary gradients:\n');
    fprintf(fid, '#   time_shape_id of 0 means default timing (stepping with grad_raster starting at 1/2 of grad_raster)\n');
    fprintf(fid, '# id amplitude amp_shape_id time_shape_id delay\n'); % do we need delay ???
    fprintf(fid, '# ..      Hz/m       ..         ..          us\n');
    fprintf(fid, '[GRADIENTS]\n');
    keys = obj.gradLibrary.keys;
    for k = keys(arbGradMask)
        fprintf(fid, '%d %12g %d %d %d\n', ...
                [k obj.gradLibrary.data(k).array(1:3) ...
                 round(obj.gradLibrary.data(k).array(4)*1e6)]);
    end
    fprintf(fid, '\n');
end

if any(trapGradMask)
    fprintf(fid, '# Format of trapezoid gradients:\n');
    fprintf(fid, '# id amplitude rise flat fall delay\n');
    fprintf(fid, '# ..      Hz/m   us   us   us    us\n');
    fprintf(fid, '[TRAP]\n');
    keys = obj.gradLibrary.keys;
    for k = keys(trapGradMask)
        data = obj.gradLibrary.data(k).array;
        data(2:end) = round(1e6*data(2:end));
        fprintf(fid, '%2d %12g %3d %4d %3d %3d\n', [k data]);
    end
    fprintf(fid, '\n');
end

if ~isempty(obj.adcLibrary.keys)
    fprintf(fid, '# Format of ADC events:\n');
    fprintf(fid, '# id num dwell delay freq phase\n');
    fprintf(fid, '# ..  ..    ns    us   Hz   rad\n');
    fprintf(fid, '[ADC]\n');
    keys = obj.adcLibrary.keys;
    for k = keys
        data = obj.adcLibrary.data(k).array(1:5).*[1 1e9 1e6 1 1];
        fprintf(fid, '%d %d %.0f %.0f %g %g\n', [k data]);
    end
    fprintf(fid, '\n');
end

%if ~isempty(obj.delayLibrary.keys)
%    fprintf(fid, '# Format of delays:\n');
%    fprintf(fid, '# id delay (us)\n');
%    fprintf(fid, '[DELAYS]\n');
%    keys = obj.delayLibrary.keys;
%    for k = keys
%        fprintf(fid, '%d %d\n', ...
%                [k round(1e6*obj.delayLibrary.data(k).array)]);
%    end
%    fprintf(fid, '\n');
%end

if ~isempty(obj.extensionLibrary.keys)
    fprintf(fid, '# Format of extension lists:\n');
    fprintf(fid, '# id type ref next_id\n');
    fprintf(fid, '# next_id of 0 terminates the list\n');
    fprintf(fid, '# Extension list is followed by extension specifications\n');
    fprintf(fid, '[EXTENSIONS]\n');
    keys = obj.extensionLibrary.keys;
    for k = keys
        fprintf(fid, '%d %d %d %d\n', ...
                [k round(obj.extensionLibrary.data(k).array)]);
    end
    fprintf(fid, '\n');
end

if ~isempty(obj.trigLibrary.keys)
    fprintf(fid, '# Extension specification for digital output and input triggers:\n');
    fprintf(fid, '# id type channel delay (us) duration (us)\n');
%     fprintf(fid, 'extension TRIGGERS 1\n'); % fixme: extension ID 1 is hardcoded here for triggers
    fprintf(fid, ['extension TRIGGERS ',num2str(obj.getExtensionTypeID('TRIGGERS')),'\n']);

    keys = obj.trigLibrary.keys;
    for k = keys
        fprintf(fid, '%d %d %d %d %d\n', ...
                [k round(obj.trigLibrary.data(k).array.*[1 1 1e6 1e6])]);
    end
    fprintf(fid, '\n');
end

if ~isempty(obj.labelsetLibrary.keys)
    lbls=mr.getSupportedLabels();

    fprintf(fid, '# Extension specification for setting labels:\n');
    fprintf(fid, '# id set labelstring\n');
    tid=obj.getExtensionTypeID('LABELSET');
    fprintf(fid, ['extension LABELSET ',num2str(tid),'\n']);
    keys = obj.labelsetLibrary.keys;
    for k = keys
            fprintf(fid, '%d %d %s\n', ...
                k, obj.labelsetLibrary.data(k).array(1),lbls{obj.labelsetLibrary.data(k).array(2)});
    end
    fprintf(fid, '\n');

    fprintf(fid, '# Extension specification for setting labels:\n');
    fprintf(fid, '# id set labelstring\n');
    tid=obj.getExtensionTypeID('LABELINC');
    fprintf(fid, ['extension LABELINC ',num2str(tid),'\n']);
    lbls=mr.getSupportedLabels();
    keys = obj.labelincLibrary.keys;
    for k = keys
            fprintf(fid, '%d %d %s\n', ...
                k, obj.labelincLibrary.data(k).array(1),lbls{obj.labelincLibrary.data(k).array(2)});
    end
    fprintf(fid, '\n');
end

if ~isempty(obj.shapeLibrary.keys)
    fprintf(fid, '# Sequence Shapes\n');
    fprintf(fid, '[SHAPES]\n\n');
    keys = obj.shapeLibrary.keys;
    for k = keys
        shape_dat = obj.shapeLibrary.data(k).array;
        fprintf(fid, 'shape_id %d\n', k);
        fprintf(fid, 'num_samples %d\n', shape_dat(1));
        fprintf(fid, '%.9g\n', shape_dat(2:end));
        fprintf(fid, '\n');
    end
end

fclose(fid);

if create_signature
    % sign the file (this version with re/loading the file is a factor 2 faster than the sprintf() based one that kept a memory-copy of the data written)

    % re-open and read in the file
    fid=fopen(filename, 'r');
    buf=fread(fid);
    fclose(fid);

    % calculate the digest
    md5hash=md5_java(buf);
    %fprintf('%s\n',md5hash);

    % store the signature in the object
    obj.signatureType='md5';
    obj.signatureFile='text';
    obj.signatureValue=md5hash;

    % re-open the file for appending
    fid=fopen(filename, 'a');
    fprintf(fid, '\n[SIGNATURE]\n'); % the preceding new line BELONGS to the signature (and needs to be sripped away to recalculate the signature)
    fprintf(fid, '# This is the hash of the Pulseq file, calculated right before the [SIGNATURE] section was added\n');
    fprintf(fid, '# It can be reproduced/verified with md5sum if the file trimmed to the position right above [SIGNATURE]\n');
    fprintf(fid, '# The new line character preceding [SIGNATURE] BELONGS to the signature (and needs to be sripped away for recalculating/verification)\n');
    fprintf(fid, 'Type md5\n');
    fprintf(fid, 'Hash %s\n', md5hash);
    fclose(fid);
end

end

function out=md5_java(buf)
    import java.security.*;
    import java.math.*;
    import java.lang.String;

    md = MessageDigest.getInstance('MD5');
    hash = md.digest(double(buf));
    bi = BigInteger(1, hash);

    out=char(String.format('%032x', bi));
end


function [ds]=sap2000elementos14(filenam)
%%%%%%%%%%%%%%%%%%           SAP2000 v14           %%%%%%%%%%%%%%%%%%%%%
%programa registrado por MECAVIL ingenieria-ciencia
%bresler_lin@hotmail.com
%%%este programa enumera los elementos y su nudo inicial y final
%arc=fopen('quimica3.$2k','r');
%filenam
arc=fopen(filenam,'r');
arc;
encuentra =0;
while encuentra==0
    linea=fgets(arc);
    if not(isempty(findstr('CONNECTIVITY - FRAME',linea)));
        encuentra=1;
   end
end
 conecc=[0;0;0];
 linea=fgets(arc);
 f=1;
 encuentra=0;
 while encuentra==0;
     [s1 s2 s3 s4 ] = strread(linea,'%s %s %s %s');
      s1=char(s1);s2=char(s2);s3=char(s3);
      v=[s1,s2,s3];
 [e1 e2]=strread(v,'%s %f ', 'delimiter',' =')  ;
  conecc=[ conecc e2(:,1)];
     f=f+1;
     linea=fgets(arc);
     linea;
     if not (isempty(findstr('COORDINATE SYSTEMS',linea)))
         encuentra=1;
     end
 end
 fclose(arc);
   conecc(:,1)=[];
   conecc= conecc';
    conecc;
  [aw1 aw2]=size( conecc)

  ds=[0 0 0];
  for i=1:1:aw1;
      ds=[ds;conecc(i,:)];
  end
  ds(1,:)=[];
inifr=ds(:,2);
finfr=ds(:,3);
  save elemento.txt ds -ASCII  ;%%%%%LOPUSE por no corregir las inercias
    save conecctividad.txt ds -ASCII  ;
%save quimicainicio.txt inifr -ASCII  ;
%save quimicafin.txt finfr -ASCII  ;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MRiLab auto generated file: DO NOT EDIT!     %
% Generated by MRiLab "DoWriteXML2m" Generator %
% MRiLab Version 1.3                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [B1x, B1y, B1z, E1x, E1y, E1z, Pos]=Coil_9ChSurfChest
%====================================
p.Azimuth=pi/2;
p.CoilID=1;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=-0.1;
p.PosY=-0.1;
p.PosZ=-0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=2;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=-0.1;
p.PosY=-0.1;
p.PosZ=0;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=3;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=-0.1;
p.PosY=-0.1;
p.PosZ=0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=4;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0;
p.PosY=-0.1;
p.PosZ=-0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=5;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0;
p.PosY=-0.1;
p.PosZ=0;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=6;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0;
p.PosY=-0.1;
p.PosZ=0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=7;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0.1;
p.PosY=-0.1;
p.PosZ=-0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=8;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0.1;
p.PosY=-0.1;
p.PosZ=0;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
p.Azimuth=pi/2;
p.CoilID=9;
p.CurrentDir=1;
p.Elevation=0;
p.PosX=0.1;
p.PosY=-0.1;
p.PosZ=0.1;
p.Radius=0.04;
p.Scale=0.1;
p.Segment=20;
[B1xt, B1yt, B1zt, E1xt, E1yt, E1zt, Post]=CoilCircle(p);
B1x(:,:,:,p.CoilID)=B1xt;
B1y(:,:,:,p.CoilID)=B1yt;
B1z(:,:,:,p.CoilID)=B1zt;
E1x(:,:,:,p.CoilID)=E1xt;
E1y(:,:,:,p.CoilID)=E1yt;
E1z(:,:,:,p.CoilID)=E1zt;
Pos(p.CoilID,:)=Post;
p=[];
%--------------------
end


function y = vecsym(x,K) %#ok
% y = vecsym(x,K)
%
% VECSYM  For the PSD submatrices, we let Yk = (Xk+Xk')/2
%
% **********  INTERNAL FUNCTION OF SEDUMI **********
%
% See also sedumi

% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% 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.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA

%Indicate to the user Matlab cannot find the SeDuMi binaries
sedumi_binary_error();


function failed_bug2396

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_read_headshape

cd(dccnpath('/home/common/matlab/fieldtrip/data/test/bug2396'));

%% define the files

mrifile = 'nobias_KR.nii';
labelfile = 'segmentation/brainsuite/nobias_KR.label.nii';

dfsfile = {
  'segmentation/brainsuite/nobias_KR.brain.dfs'
  'segmentation/brainsuite/nobias_KR.inner_skull.dfs'
  'segmentation/brainsuite/nobias_KR.outer_skull.dfs'
  'segmentation/brainsuite/nobias_KR.scalp.dfs'
  };

meshfile = {
  'segmentation/brainvisa/nobias_KR_BEM_brain.mesh'
  'segmentation/brainvisa/nobias_KR_BEM_head.mesh'
  'segmentation/brainvisa/nobias_KR_BEM_skull.mesh'
  'segmentation/brainvisa/nobias_KR_head.mesh'
  };

% the following contain metadata that goes with the mesh files
% segmentation/brainvisa/nobias_KR_BEM_brain.mesh.minf
% segmentation/brainvisa/nobias_KR_BEM_head.mesh.minf
% segmentation/brainvisa/nobias_KR_BEM_skull.mesh.minf
% segmentation/brainvisa/nobias_KR_head.mesh.minf

surffile = {
  'segmentation/freesurfer/lh.BEM_brain_surface.surf'
  'segmentation/freesurfer/lh.BEM_inner_skull_surface.surf'
  'segmentation/freesurfer/lh.BEM_outer_skin_surface.surf'
  'segmentation/freesurfer/lh.BEM_outer_skull_surface.surf'
  };

%% read the content from the files

mri = ft_read_mri(mrifile);

% it would be more consistent to read it with ft_read_atlas, as if it were a ft_datatype_segmentation
seg = ft_read_mri(labelfile);

% dress up the segmentation
seg.anatomylabel = {};
seg.anatomylabel{19} = 'brain';
seg.anatomylabel{18} = 'csf';
seg.anatomylabel{17} = 'skull';
seg.anatomylabel{16} = 'scalp';
seg.coordsys = 'ctf'; % it seems to be in CTF coordinates, i.e. positive y axis through nasion

cfg = [];
cfg.atlas = seg; % use itself as the atlas to look up the number-name mappings
ft_sourceplot(cfg, seg);

%% read the content from the files

dfs = {};
figure
for i=1:4
  dfs{i} = ft_read_headshape(dfsfile{i});
  ft_plot_mesh(dfs{i}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);
end

mesh = {};
figure
for i=1:4
  mesh{i} = ft_read_headshape(meshfile{i});
  ft_plot_mesh(mesh{i}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);
  % note that mesh number 4 is ugly and has internal structures
end

surf = {};
figure
for i=1:4
  surf{i} = ft_read_headshape(surffile{i});
  ft_plot_mesh(surf{i}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);
end

% plot them together, this should form a consistent set
ft_plot_mesh(dfs{1}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);
ft_plot_mesh(mesh{3}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);
ft_plot_mesh(surf{3}, 'edgecolor', 'none', 'facecolor', [1 1 1]/2, 'facealpha', 0.3);

dfsall = cellfun(@ft_read_headshape, dfsfile);


function vl_printsize(varargin)
% VL_PRINTSIZE  Set the printing size of a figure
%   VL_PRINTSIZE(R) adjusts the PaperPosition property of the current
%   figure to make the figure paper width equal to R times the width
%   of a 'uslsetter' page, while preserving the aspect ratio of the
%   figure. Then, it sets the PaperSize property to match tightly the
%   size of the figure.
%
%   VL_PRINTSIZE(FIG,R) operates on the specified figure FIG. The
%   function accepts the following optional arguments:
%
%   AspectRatio:: []
%     Change the figure aspect ratio (width/height) to the specified
%     value.
%
%   Reference:: 'horizontal'
%     If set to 'horizontal', VL_PRINTSIZE(R) makes the width of the
%     figure equal to a fraction R of the width of the page. If set to
%     'vertical', the height is used instead.
%
%   PaperType:: 'usletter'
%     Set the type of the reference page to the specified type. Any of
%     the paper types supported by MATLAB can be used (see
%     PRINT()).
%
%   Margin:: 0
%     If greater than zero, VL_PRINTSIZE(R) leaves the specified
%     margin around the figure rather than fitting the paper size
%     tightly around it. The margin is expressed as a fraction of the
%     figure paper width (or height if Reference is set to
%     'vertical').
%
%   PRINTING FIGURES IN MATLAB
%
%   The standard procedure to include a MATLAB figure in a publication
%   consists in printing the figure to an EPS or PDF file (by using
%   the PRINT() function) and then rescaling it to the desired size in
%   the publication. PDF printing has the additional inconvenience
%   that large white margins are generated, and requires cropping the
%   figure too.
%
%   Unfortunately, rescalign a figure in this manner has the usually
%   unwanted effect of rescaling elements of the graphics such as font
%   sizes and line thicknesses. For example, a font which is 12pt in
%   the original MATLAB figure may become too large or too small after
%   rescaling.
%
%   The `proper' way of printing a figure is to specify its desired
%   size on paper before calling the PRINT() function. VL_PRINTSIZE()
%   helps doing so.
%
%   Margins are an additional nuances. When printing to certain
%   formats such as PDF, MATLAB prints in fact entire page (e.g. a
%   whole US Letter sheet), resulting in wide white margin all around
%   the figure. VL_PRINTSIZE() alleviates this problem by setting the
%   paper size to match the figure size tightly. This does not
%   eliminate margins completely, especially if the figure has
%   multiple subplots, but it is certainly a large improvement.
%
%   See also: VL_HELP().

% Author: Andrea Vedaldi

% Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
% Copyright (C) 2013 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

if length(varargin) >= 2 && isnumeric(varargin{2})
  % called with two numeric arguments
  fig = varargin{1} ;
  varargin(1) = [] ;
else
  fig = gcf ;
end

sizeRatio = varargin{1} ;
varargin(1) = [] ;

opts.aspectRatio = NaN ;
opts.reference = 'horizontal' ;
opts.paperType = 'usletter' ;
opts.margin = 0 ;
opts = vl_argparse(opts, varargin) ;

opts.reference = lower(opts.reference) ;
if ~ismember(opts.reference, {'horizontal', 'vertical'})
  error('Invalid value ''%s'' for the REFERENCE option', opts.reference) ;
end

% set the paper size to the reference type
if ~isempty(opts.paperType)
    set(fig, 'PaperType', opts.paperType) ;
end
paperSize = get(fig, 'PaperSize') ;

% get the current figure position to compute the current aspect ratio
position = get(fig, 'PaperPosition') ;

% if not specified, compute current aspect ratio
if isnan(opts.aspectRatio)
  opts.aspectRatio = position(3) / position(4) ;
end

% resize the figure
switch opts.reference
  case 'horizontal'
    s = paperSize(1) * sizeRatio ;
  case 'vertical'
    s = paperSize(2) * sizeRatio * opts.aspectRatio ;
end
position(3:4) =  s * [1 1/opts.aspectRatio] ;

% add margin
switch opts.reference
  case 'horizontal'
    position(1) = position(3) * opts.margin ;
    position(2) = position(3) * opts.margin ;
  case 'vertical'
    position(1) = position(4) * opts.margin ;
    position(2) = position(4) * opts.margin ;
end

set(fig, ...
  'PaperPosition', position, ...
  'PaperSize', 2 * position(1:2) + position(3:4)) ;

end


% std_maketrialinfo() - create trial information structure using the
%                       .epoch structure of EEGLAB datasets
%
% Usage:
%   >> STUDY = std_maketrialinfo(STUDY, ALLEEG);
%
% Inputs:
%   STUDY      - EEGLAB STUDY set
%   ALLEEG     - vector of the EEG datasets included in the STUDY structure
%
% Inputs:
%   STUDY      - EEGLAB STUDY set updated. The fields which is created or
%                updated is STUDY.datasetinfo.trialinfo
%
% Authors: Arnaud Delorme, SCCN/INC/UCSD, April 2010

% Copyright (C) Arnaud Delorme arno@ucsd.edu
%
% 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 STUDY = std_maketrialinfo(STUDY, ALLEEG);

%% test if .epoch field exist in ALLEEG structure
epochfield = cellfun(@isempty, { ALLEEG.epoch });
if any(epochfield)
    fprintf('Warning: some datasets are continuous and trial information cannot be created\n');
    return;
end;

%% Make trial info
for index = 1:length(ALLEEG)
    eventlat = abs(eeg_point2lat( [ ALLEEG(index).event.latency ], [ ALLEEG(index).event.epoch ], ALLEEG(index).srate, [ALLEEG(index).xmin ALLEEG(index).xmax]));
    events   = ALLEEG(index).event;
    ff = fieldnames(events);
    ff = setdiff(ff, { 'latency' 'urevent' 'epoch' });
    trialinfo = [];

    % process time locking event fields
    % ---------------------------------
    indtle    = find(eventlat < 0.02);
    epochs    = [ events(indtle).epoch ];
    extractepoch = true;
    if length(epochs) ~= ALLEEG(index).trials

        % special case where there are not the same number of time-locking
        % event as there are data epochs
        if length(unique(epochs)) ~= ALLEEG(index).trials
            extractepoch = false;
            disp('std_maketrialinfo: not the same number of time-locking events as trials, trial info ignored');
        else
            % pick one event per epoch
            [tmp tmpind] = unique(epochs(end:-1:1)); % reversing the array ensures the first event gets picked
            tmpind = length(epochs)+1-tmpind;
            indtle = indtle(tmpind);
            if length(indtle) ~= ALLEEG(index).trials
                extractepoch = false;
                disp('std_maketrialinfo: not the same number of time-locking events as trials, trial info ignored');
            end;
        end;
    end;
    if extractepoch
        commands = {};
        for f = 1:length(ff)
            eval( [ 'eventvals = {events(indtle).' ff{f} '};' ]);
            %if isnumeric(eventvals{1})
            %    eventvals = cellfun(@num2str, eventvals, 'uniformoutput', false);
            %end;
            commands = { commands{:} ff{f} eventvals };
        end;
        trialinfo = struct(commands{:});
        STUDY.datasetinfo(index).trialinfo = trialinfo;
    end;

%    % same as above but 10 times slower
%     for e = 1:length(ALLEEG(index).event)
%         if eventlat(e) < 0.0005 % time locking event only
%             epoch = events(e).epoch;
%             for f = 1:length(ff)
%                 fieldval  = getfield(events, {e}, ff{f});
%                 trialinfo = setfield(trialinfo, {epoch}, ff{f}, fieldval);
%             end;
%         end;
%     end;
end;


% finputcheck() - check Matlab function {'key','value'} input argument pairs
%
% Usage: >> result = finputcheck( varargin, fieldlist );
%        >> [result varargin] = finputcheck( varargin, fieldlist, ...
%                                              callingfunc, mode, verbose );
% Input:
%   varargin  - Cell array 'varargin' argument from a function call using 'key',
%               'value' argument pairs. See Matlab function 'varargin'
%   fieldlist - A 4-column cell array, one row per 'key'. The first
%               column contains the key string, the second its type(s),
%               the third the accepted value range, and the fourth the
%               default value.  Allowed types are 'boolean', 'integer',
%               'real', 'string', 'cell' or 'struct'.  For example,
%                       {'key1' 'string' { 'string1' 'string2' } 'defaultval_key1'}
%                       {'key2' {'real' 'integer'} { minint maxint } 'defaultval_key2'}
%  callingfunc - Calling function name for error messages. {default: none}.
%  mode        - ['ignore'|'error'] ignore keywords that are either not specified
%                in the fieldlist cell array or generate an error.
%                {default: 'error'}.
%  verbose     - ['verbose', 'quiet'] print information. Default: 'verbose'.
%
% Outputs:
%   result     - If no error, structure with 'key' as fields and 'value' as
%                content. If error this output contain the string error.
%   varargin   - residual varagin containing unrecognized input arguments.
%                Requires mode 'ignore' above.
%
% Note: In case of error, a string is returned containing the error message
%       instead of a structure.
%
% Example (insert the following at the beginning of your function):
%	result = finputcheck(varargin, ...
%               { 'title'         'string'   []       ''; ...
%                 'percent'       'real'     [0 1]    1 ; ...
%                 'elecamp'       'integer'  [1:10]   [] });
%   if isstr(result)
%       error(result);
%   end
%
% Note:
%   The 'title' argument should be a string. {no default value}
%   The 'percent' argument should be a real number between 0 and 1. {default: 1}
%   The 'elecamp' argument should be an integer between 1 and 10 (inclusive).
%
%   Now 'g.title' will contain the title arg (if any, else the default ''), etc.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 10 July 2002

% Copyright (C) Arnaud Delorme, CNL / Salk Institute, 10 July 2002, arno@salk.edu
%
% 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 [g, varargnew] = finputcheck( vararg, fieldlist, callfunc, mode, verbose )

	if nargin < 2
		help finputcheck;
		return;
	end;
	if nargin < 3
		callfunc = '';
	else
		callfunc = [callfunc ' ' ];
	end;
    if nargin < 4
        mode = 'do not ignore';
    end;
    if nargin < 5
        verbose = 'verbose';
    end;
	NAME = 1;
	TYPE = 2;
	VALS = 3;
	DEF  = 4;
	SIZE = 5;

	varargnew = {};
	% create structure
	% ----------------
	if ~isempty(vararg)
		for index=1:length(vararg)
			if iscell(vararg{index})
				vararg{index} = {vararg{index}};
			end;
		end;
		try
			g = struct(vararg{:});
		catch
            vararg = removedup(vararg, verbose);
            try
                g = struct(vararg{:});
            catch
                g = [ callfunc 'error: bad ''key'', ''val'' sequence' ]; return;
            end;
		end;
	else
		g = [];
	end;

	for index = 1:size(fieldlist,NAME)
		% check if present
		% ----------------
		if ~isfield(g, fieldlist{index, NAME})
			g = setfield( g, fieldlist{index, NAME}, fieldlist{index, DEF});
		end;
		tmpval = getfield( g, {1}, fieldlist{index, NAME});

		% check type
		% ----------
        if ~iscell( fieldlist{index, TYPE} )
            res = fieldtest( fieldlist{index, NAME},  fieldlist{index, TYPE}, ...
                           fieldlist{index, VALS}, tmpval, callfunc );
            if isstr(res), g = res; return; end;
        else
            testres = 0;
            tmplist = fieldlist;
            for it = 1:length( fieldlist{index, TYPE} )
                if ~iscell(fieldlist{index, VALS})
                     res{it} = fieldtest(  fieldlist{index, NAME},  fieldlist{index, TYPE}{it}, ...
                                           fieldlist{index, VALS}, tmpval, callfunc );
                else res{it} = fieldtest(  fieldlist{index, NAME},  fieldlist{index, TYPE}{it}, ...
                                           fieldlist{index, VALS}{it}, tmpval, callfunc );
                end;
                if ~isstr(res{it}), testres = 1; end;
            end;
            if testres == 0,
                g = res{1};
                for tmpi = 2:length(res)
                    g = [ g 10 'or ' res{tmpi} ];
                end;
                return;
            end;
        end;
	end;

    % check if fields are defined
	% ---------------------------
	allfields = fieldnames(g);
	for index=1:length(allfields)
		if isempty(strmatch(allfields{index}, fieldlist(:, 1)', 'exact'))
			if ~strcmpi(mode, 'ignore')
				g = [ callfunc 'error: undefined argument ''' allfields{index} '''']; return;
			end;
			varargnew{end+1} = allfields{index};
			varargnew{end+1} = getfield(g, {1}, allfields{index});
		end;
	end;

function g = fieldtest( fieldname, fieldtype, fieldval, tmpval, callfunc );
	NAME = 1;
	TYPE = 2;
	VALS = 3;
	DEF  = 4;
	SIZE = 5;
    g = [];

    switch fieldtype
     case { 'integer' 'real' 'boolean' 'float' },
      if ~isnumeric(tmpval) && ~islogical(tmpval)
          g = [ callfunc 'error: argument ''' fieldname ''' must be numeric' ]; return;
      end;
      if strcmpi(fieldtype, 'boolean')
          if tmpval ~=0 && tmpval ~= 1
              g = [ callfunc 'error: argument ''' fieldname ''' must be 0 or 1' ]; return;
          end;
      else
          if strcmpi(fieldtype, 'integer')
              if ~isempty(fieldval)
                  if (any(isnan(tmpval(:))) && ~any(isnan(fieldval))) ...
                          && (~ismember(tmpval, fieldval))
                      g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
                  end;
              end;
          else % real or float
              if ~isempty(fieldval) && ~isempty(tmpval)
                  if any(tmpval < fieldval(1)) || any(tmpval > fieldval(2))
                      g = [ callfunc 'error: value out of range for argument ''' fieldname '''' ]; return;
                  end;
              end;
          end;
      end;

     case 'string'
      if ~isstr(tmpval)
          g = [ callfunc 'error: argument ''' fieldname ''' must be a string' ]; return;
      end;
      if ~isempty(fieldval)
          if isempty(strmatch(lower(tmpval), lower(fieldval), 'exact'))
              g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
          end;
      end;

     case 'cell'
      if ~iscell(tmpval)
          g = [ callfunc 'error: argument ''' fieldname ''' must be a cell array' ]; return;
      end;

     case 'struct'
      if ~isstruct(tmpval)
          g = [ callfunc 'error: argument ''' fieldname ''' must be a structure' ]; return;
      end;

     case '';
     otherwise, error([ 'finputcheck error: unrecognized type ''' fieldname '''' ]);
    end;

% remove duplicates in the list of parameters
% -------------------------------------------
function cella = removedup(cella, verbose)
% make sure if all the values passed to unique() are strings, if not, exist
%try
    [tmp indices] = unique(cella(1:2:end));
    if length(tmp) ~= length(cella)/2
        myfprintf(verbose,'Note: duplicate ''key'', ''val'' parameter(s), keeping the last one(s)\n');
    end;
    cella = cella(sort(union(indices*2-1, indices*2)));
%catch
    % some elements of cella were not string
%    error('some ''key'' values are not string.');
%end;

function myfprintf(verbose, varargin)

if strcmpi(verbose, 'verbose')
    fprintf(varargin{:});
end;


function mtrCreateConTracParallelScript(machineList, binDirName, exeConTracFile, scriptFileName, scriptOptsFile, pathsRoot)

% createConTrackParallelScript(machineList, binDirName, exeConTracFile,
% scriptFileName, scriptOptsFile, pathsRoot)

% Create script for parallel processing of pathway tracing on DLs
NN = length(machineList); % compute nodes
fid = fopen(scriptFileName,'wt');
fprintf(fid,'#!/bin/bash\n');
offset = 0;
for nn = 1:NN
    mach_num = floor((nn-1)/2) + 1;
    sub_n = 2 - mod(nn,2);
    paramsFile = fullfile(binDirName,'conTrack',scriptOptsFile);
    pathsFile = fullfile(binDirName,'conTrack',sprintf('%s_%d.dat',pathsRoot,nn+offset));
    fprintf(fid,'echo ''Compute %s''\n',machineList{nn});
    fprintf(fid,'ssh %s %s -i %s -p %s &\n', machineList{nn}, exeConTracFile, paramsFile, pathsFile);
    fprintf(fid,'sleep 2\n');
end
fclose(fid);