% pop_epoch() - Convert a continuous EEG dataset to epoched data by extracting
%               data epochs time locked to specified event types or event indices.
%               May also sub-epoch an already epoched dataset (if sub-epochs are
%               same size or smaller). This pop_function calls epoch().
% Usage:
%   >> OUTEEG = pop_epoch( EEG); % pop-up a data entry window
%   >> OUTEEG = pop_epoch( EEG, events, timelimits);
%   >> [OUTEEG, indices] = pop_epoch( EEG, typerange, timelimits,'key1', value1 ...);
%
% Graphic interface:
%   "Time-locking event type(s)" - [edit box] Select 'Edit > Event values'
%                to see a list of event.type values; else use the push button.
%                To use event types containing spaces, enter in single-quotes.
%                epoch() function command line equivalent: 'typerange'
%   "..."      - [push button] scroll event types.
%   "Epoch limits" - [edit box] epoch latency range [start, end] in seconds relative
%                to the time-locking events. epoch() function equivalent: 'timelim'
%   "Name for the new dataset" - [edit box]
%                epoch() function equivalent: 'newname'
%   "Out-of-bounds EEG ..." - [edit box] Rejection limits ([min max], []=none).
%                epoch() function equivalent: 'valuelim'
% Inputs:
%   EEG        - Input dataset. Data may already be epoched; in this case,
%                extract (shorter) subepochs time locked to epoch events.
%   typerange  - Cell array of event types to time lock to. 'eventindices'
%                {default {} --> time lock epochs to any type of event}
%                (Note: An event field called 'type' must be defined in the
%                'EEG.event' structure. The command line argument is
%                'eventindices' below).
%   timelim    - Epoch latency limits [start end] in seconds relative to
%                the time-locking event {default: [-1 2]}
%
% Optional inputs:
%   'eventindices'- [integer vector] Extract data epochs time locked to the
%                indexed event numbers.
%   'valuelim' - [min max] or [max]. Lower and upper bound latencies for
%                trial data. Else if one positive value is given, use its
%                negative as the lower bound. The given values are also
%                considered outliers (min max) {default: none}
%   'verbose'  - ['yes'|'no'] {default: 'yes'}
%   'newname'  - [string] New dataset name {default: "[old_dataset] epochs"}
%   'epochinfo'- ['yes'|'no'] Propagate event information into the new
%                epoch structure {default: 'yes'}
%
% Outputs:
%   OUTEEG     - output dataset
%   indices    - indices of accepted events
%
% Authors: Arnaud Delorme and Hilit Serby, SCCN, INC, UCSD, 2001
%
% See also: eeglab, epoch

% deprecated
%   'timeunit' - Time unit ['seconds'|'points'] If 'seconds,' consider events
%                times to be in seconds. If 'points,' consider events as
%                indices into the data array. {default: 'points'}

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

% 01-25-02 reformated help & license -ad
% 02-13-02 introduction of 'key', val arguments -ad
% 02-13-02 rereferencing of events -ad
% 03-18-02 interface and debugging -ad
% 03-27-02 interface and debugging -ad & sm

function [EEG, indices, com] = pop_epoch( EEG, events, lim, varargin );

if nargin < 1
   help pop_epoch;
	return;
end;
com = '';
indices = [];

if isempty(EEG.event)
    if EEG.trials > 1 & EEG.xmin <= 0 & EEG.xmax >=0
        disp('No EEG.event structure found: creating events of type ''TLE'' (Time-Locking Event) at time 0');
        EEG.event(EEG.trials).epoch = EEG.trials;
        for trial = 1:EEG.trials
            EEG.event(trial).epoch   = trial;
            EEG.event(trial).type    = 'TLE';
            EEG.event(trial).latency = -EEG.xmin*EEG.srate+1+(trial-1)*EEG.pnts;
        end;
    else
        disp('Cannot epoch data with no events'); beep;
        return;
    end;
end;
if ~isfield(EEG.event, 'latency'),
    disp( 'Absent latency field in event array/structure: must name one of the fields ''latency''');
     beep; return;
end;
if size(EEG.data,3) > 1
    epochlim = [num2str( round(EEG.xmin*1000,1)) '  '  num2str(round(EEG.xmax*1000,1))];
else
    epochlim = '-1 2';
end
OLDEEG = EEG;

if nargin < 3
	% popup window parameters
	% -----------------------
   promptstr    = { strvcat('Time-locking event type(s) ([]=all):', ...
                    'Select ''Edit > Event values'' to see type values.'), ...
                    'Epoch limits [start, end] in seconds:', ...
                    'Name for the new dataset:', ...
					'Out-of-bounds EEG rejection limits ([min max], []=none):'  };

   cbevent = ['if ~isfield(EEG.event, ''type'')' ...
				   '   errordlg2(''No type field'');' ...
				   'else' ...
                   '   tmpevent = EEG.event;' ...
                   '   if isnumeric(EEG.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'', ''events''), ''string'', tmpstr);' ...
				   '   end;' ...
				   'end;' ...
				   'clear tmps tmpevent tmpv tmpstr tmpfieldnames;' ];

   geometry = { [2 1 0.5] [2 1 0.5] [2 1.5] [2 1 0.5] };
   uilist = { { 'style' 'text'       'string' 'Time-locking event type(s) ([]=all)' } ...
              { 'style' 'edit'       'string' '' 'tag' 'events' } ...
              { 'style' 'pushbutton' 'string' '...' 'callback' cbevent } ...
              { 'style' 'text'       'string' 'Epoch limits [start, end] in seconds' } ...
              { 'style' 'edit'       'string' epochlim } ...
              { } ...
              { 'style' 'text'       'string' 'Name for the new dataset' } ...
              { 'style' 'edit'       'string'  fastif(isempty(EEG.setname), '', [ EEG.setname ' epochs' ]) } ...
              { 'style' 'text'       'string' 'Out-of-bounds EEG limits if any [min max]' } ...
              { 'style' 'edit'       'string' '' } { } };

   result = inputgui( geometry, uilist, 'pophelp(''pop_epoch'')', 'Extract data epochs - pop_epoch()');
   if length(result) == 0 return; end;

   if strcmpi(result{1}, '[]'), result{1} = ''; end;
   if ~isempty(result{1})
       if strcmpi(result{1}(1),'''')   % If event type appears to be in single-quotes, use comma
                                       % and single-quote as delimiter between event types. toby 2.24.2006
                                       % fixed Arnaud May 2006
            events = eval( [ '{' result{1} '}' ] );
       else events = parsetxt( result{1});
       end;
   else events = {};
   end
   lim = eval( [ '[' result{2} ']' ] );

   args = {};
   if ~isempty( result{3} ),  args = { args{:}, 'newname', result{3} }; end;
   if ~isempty( result{4} ),  args = { args{:}, 'valuelim', eval( [ '[' result{4} ']' ] ) }; end;
   args = { args{:}, 'epochinfo', 'yes' };

else % no interactive inputs
    args = varargin;
end;

% create structure
% ----------------
if ~isempty(args)
   try, g = struct(args{:});
   catch, disp('pop_epoch(): wrong syntax in function arguments'); return; end;
else
    g = [];
end;

% test the presence of variables
% ------------------------------
try, g.epochfield; 	 	  catch, g.epochfield = 'type'; end; % obsolete
try, g.timeunit; 	 	  catch, g.timeunit = 'points'; end;
try, g.verbose; 	      catch, g.verbose = 'on'; end;
try, g.newname; 	      catch, g.newname = fastif(isempty(EEG.setname), '', [EEG.setname ' epochs' ]); end;
try, g.eventindices;      catch, g.eventindices = 1:length(EEG.event); end;
try, g.epochinfo;         catch, g.epochinfo = 'yes'; end;
try, if isempty(g.valuelim), g.valuelim = [-Inf Inf]; end; catch, g.valuelim = [-Inf Inf]; end;

% transform string events into a int array of column indices
% ----------------------------------------------------------
tmpevent = EEG.event;
tmpeventlatency = [ tmpevent(:).latency ];
[tmpeventlatency Itmp] = sort(tmpeventlatency);
EEG.event = EEG.event(Itmp);  % sort by ascending time
Ievent = g.eventindices;

if ~isempty( events )
    % select the events for epoching
    % ------------------------------
    Ieventtmp = [];
    tmpevent = EEG.event;
    tmpeventtype  = { tmpevent.type };
    if iscell(events)
		if isstr(EEG.event(1).type)
			for index2 = 1:length( events )
				tmpevent = events{index2};
				if ~isstr( tmpevent ), tmpevent = num2str( tmpevent ); end;
				Ieventtmp = [ Ieventtmp ; strmatch(tmpevent, tmpeventtype, 'exact') ];
			end;
		else
			for index2 = 1:length( events )
				tmpevent = events{index2};
				if isstr( tmpevent ),tmpevent = str2num( tmpevent ); end;
				if isempty( tmpevent ), error('pop_epoch(): string entered in a numeric field'); end;
				Ieventtmp = [ Ieventtmp find(tmpevent == [ tmpeventtype{:} ]) ];
			end;
		end;
    else
        error('pop_epoch(): multiple event types must be entered as {''a'', ''cell'', ''array''}'); return;
    end;
    Ievent = sort(intersect(Ievent, Ieventtmp));
end;

% select event latencies for epoching
%------------------------------------
Ievent = sort(Ievent);
alllatencies = tmpeventlatency(Ievent);

if isempty(alllatencies)
   error('pop_epoch(): empty epoch range (no epochs were found).'); return;
end;
fprintf('pop_epoch():%d epochs selected\n', length(alllatencies));

try
    % ----------------------------------------------------
    % For AMICA probabilities...Temporarily add model probabilities as channels
    %-----------------------------------------------------
    if isfield(EEG.etc, 'amica') && ~isempty(EEG.etc.amica) && isfield(EEG.etc.amica, 'v_smooth') && ~isempty(EEG.etc.amica.v_smooth) && ~isfield(EEG.etc.amica,'prob_added')
        if isfield(EEG.etc.amica, 'num_models') && ~isempty(EEG.etc.amica.num_models)
            if size(EEG.data,2) == size(EEG.etc.amica.v_smooth,2) && size(EEG.data,3) == size(EEG.etc.amica.v_smooth,3) && size(EEG.etc.amica.v_smooth,1) == EEG.etc.amica.num_models

                EEG = eeg_formatamica(EEG);
                %--------------------
                [EEG indices com] = pop_epoch(EEG,events,lim,args{:});
                %---------------------------------

                EEG = eeg_reformatamica(EEG);
                EEG = eeg_checkamica(EEG);
                return;
            else
                disp('AMICA probabilities not compatible with size of data, model probabilities cannot be epoched...')

            end
        end
    end
    % ----------------------------------------------------
catch
    warnmsg = strcat('your dataset contains amica information, but the amica plugin is not installed.  Continuing and ignoring amica information.');
    warning(warnmsg)
end

% change boundaries in rare cases when limits do not include time-locking events
% ------------------------------------------------------------------------------
tmpevents = EEG.event;
if lim(1) > 0 && ischar(EEG.event(1).type)
   % go through all onset latencies
   for Z1 = length(alllatencies):-1:1
      % if there is any event in between trigger and epoch onset which are boundary events
      selEvt = find([tmpevents.latency] > alllatencies(Z1) & [tmpevents.latency] < alllatencies(Z1) + lim(1) * EEG.srate);
      selEvt = selEvt(strcmp({tmpevents(selEvt).type}, 'boundary'));
      if any(selEvt)
          if sum([tmpevents(selEvt).duration]) > lim(1) * EEG.srate
              alllatencies(Z1) = [];
          else
              % correct the latencies by the duration of the data that were cutout
              alllatencies(Z1) = alllatencies(Z1) - sum([tmpevents(selEvt).duration]);
          end;
      end
   end
end
if lim(2) < 0 && ischar(EEG.event(1).type)
   % go through all onset latencies
   for Z1 = length(alllatencies):-1:1
      % if there is any event in between trigger and epoch onset which are boundary events
      selEvt = find([tmpevents.latency] < alllatencies(Z1) & [tmpevents.latency] > alllatencies(Z1) + lim(2) * EEG.srate);
      selEvt = selEvt(strcmp({tmpevents(selEvt).type}, 'boundary'));
      if any(selEvt)
          if sum([tmpevents(selEvt).duration]) > -lim(2) * EEG.srate
              alllatencies(Z1) = [];
          else
              % correct the latencies by the duration of the data that were cutout
              alllatencies(Z1) = alllatencies(Z1) + sum([tmpevents(selEvt).duration]);
          end;
      end
   end
end

% select event time format and epoch
% ----------------------------------
switch lower( g.timeunit )
 case 'points',	[EEG.data tmptime indices epochevent]= epoch(EEG.data, alllatencies, [lim(1) lim(2)]*EEG.srate, ...
                                                    'valuelim', g.valuelim, 'allevents', tmpeventlatency);
  tmptime = tmptime/EEG.srate;
 case 'seconds',	[EEG.data tmptime indices epochevent]= epoch(EEG.data, alllatencies, lim, 'valuelim', g.valuelim, ...
                                                    'srate', EEG.srate, 'allevents', tmpeventlatency);
	otherwise, disp('pop_epoch(): invalid event time format'); beep; return;
end;
alllatencies = alllatencies(indices);
fprintf('pop_epoch():%d epochs generated\n', length(indices));

% update other fields
% -------------------
if lim(1) ~= tmptime(1) & lim(2)-1/EEG.srate ~= tmptime(2)
	fprintf('pop_epoch(): time limits have been adjusted to [%3.3f %3.3f] to fit data points limits\n', ...
		tmptime(1), tmptime(2)+1/EEG.srate);
end;
EEG.xmin = tmptime(1);
EEG.xmax = tmptime(2);
EEG.pnts = size(EEG.data,2);
EEG.trials = size(EEG.data,3);
EEG.icaact = [];
if ~isempty(EEG.setname)
	if ~isempty(EEG.comments)
		EEG.comments = strvcat(['Parent dataset "' EEG.setname '": ----------'], EEG.comments);
	end;
	EEG.comments = strvcat(['Parent dataset: ' EEG.setname ], ' ', EEG.comments);
end;
EEG.setname = g.newname;

% count the number of events to duplicate and duplicate them
% ----------------------------------------------------------
totlen = 0;
for index=1:EEG.trials, totlen = totlen + length(epochevent{index}); end;
EEG.event(1).epoch = 0;          % create the epoch field (for assignment consistency afterwards)
if totlen ~= 0
    newevent(totlen) = EEG.event(1); % reserve array
else
    newevent = [];
end;

% modify the event structure accordingly (latencies and add epoch field)
% ----------------------------------------------------------------------
allevents = [];
count = 1;
for index=1:EEG.trials
    for indexevent = epochevent{index}
		newevent(count)         = EEG.event(indexevent);
        newevent(count).epoch   = index;
	    newevent(count).latency = newevent(count).latency ...
			- alllatencies(index) - tmptime(1)*EEG.srate + 1 + EEG.pnts*(index-1);
		count = count + 1;
    end;
end;
EEG.event = newevent;
EEG.epoch = [];
EEG = eeg_checkset(EEG, 'eventconsistency');

% check for boundary events
% -------------------------
disp('pop_epoch(): checking epochs for data discontinuity');
if ~isempty(EEG.event) & isstr(EEG.event(1).type)
    tmpevent = EEG.event;
	boundaryindex = strmatch('boundary', { tmpevent.type });
	if ~isempty(boundaryindex)
		indexepoch = [];
		for tmpindex = boundaryindex
            if isfield(tmpevent, 'epoch')
    			indexepoch = [indexepoch tmpevent(tmpindex).epoch ];
            else
                indexepoch = 1; % only one epoch
            end;
		end;
		EEG = pop_select(EEG, 'notrial', indexepoch);
        % update the "indices of accepted events", too
        indices = indices(setdiff(1:length(indices),indexepoch));
	end;
end;

% generate text command
% ---------------------
com = sprintf('%s = pop_epoch( %s, { ', inputname(1), inputname(1));
for j=1:length(events);
    if isstr( events{j} )   com = sprintf('%s ''%s'' ', com, events{j} );
    else                    com = sprintf('%s [%s] ',   com, num2str(events{j}) );
    end;
end;
com = sprintf('%s }, [%s]', com, num2str(lim));
for i=1:2:length(args)
    if ~isempty( args{i+1} )
        if isstr( args{i+1} )   com = sprintf('%s, ''%s'', ''%s''', com, args{i}, args{i+1} );
        else                    com = sprintf('%s, ''%s'', [%s]', com, args{i}, num2str(args{i+1}) );
        end;
    end;
end;
com = [com ');'];
return; % text command


function slider = mrvSlider(pos, name, varargin);
%
% slider = mrvSlider([pos], [name], [properties]);
%
% Create a slider with an attached edit field,  both of which
% specify the same value,  and a text label describing the
% parameter being set. Often used in mrVista UIs.
%
% pos: position [lrhc_x lrhc_y x_size y_size] of box containing
%      slider,  edit field,  and labels.
% name: name of slider (will be default text in the label).
%
% properties: specify in pairs,  the name of the property and
% its value. Here are the properties an mrvSlider can have:
%    'parent': parent figure or uipanel for slider. Default gcf.
%    'range': [min max] values for the slider. Default [0 1].
%    'val': initial value for the slider. Default is [min] value.
%
%    'callback': callback function for the object. When the edit field
%          or sliders are modified by the user,  the control will
%          first set the other control to agree with the value that
%          was set. (E.g., if you type a value, it will first set the
%          slider to match that value.)
%		   Then it will evaluate the cb string entered here.
%          Default cb is empty.
%          For the callback, the current value of the slider will be
%          evaluated to the temporary variable 'val', so no get functions
%          need to be added. For example:
%          'callback', 'colormap( gray( val ))' will cause the slider
%          to set the figure's colormap to the [val] number of grays after
%          a value is selected.
%
%    'units': units for slider objects. Default 'normalized',  relative
%          to parent object.
%    'intFlag': flag for whether slider value should be constrained
%          to be an integer or not. Default 0.
%    'flexFlag': flag for whether slider should be flexible for
%          values entered outside the specified range. If 0,  when
%          a value is entered into the edit field outside the min
%          and max values set by the slider,  the value is automatically
%          reset to be within the bounds. If 1,  will allow the higher
%          value,  and expand the slider's range accordingly. Default
%          is 0,  reset out-of-bound values.
%    'sigFigs': # of significant figures to show in the edit field.
%           Default is 2. If intFlag is 1,  this is overridden and 0
%           sig figs are always shown.
%    'maxLabelFlag': flag to put a small label to the side of the
%           slider indicating the maximum value. Default is 0,
%           don't add this.
%    'color': background color of the object. Default is the
%           same value as the parent object.
%    'fontSize': size of fonts for the edit / text controls.
%           Default is 12 point.
%
% Returns a slider struct with handles to the slider,  edit,  and
% label(s),  the callback strings for the slider and edit controls,
% and the values of the properties above.
%
% Properties of the mrvSlider can be set later on using
% mrvSliderSet.m.
%
% ras,  07/05/05.
% ras,  09/06 -- imported into VISTASOFT repository from mrVista 2 tools.
if nargin<2,  help(mfilename); error('Not enough args.');            end

%%%%% Default properties
parent = gcf;
range = [0 1];
cb = '';
units = 'normalized';
intFlag = 0;
flexFlag = 0;
sigFigs = 2;
maxLabelFlag = 0;
fontName = 'Helvetica';
fontSize = 12;
sliderStep = [.03 .15];
visible = 'on';

%%%%% parse the property flags
for i = 1:2:length(varargin)
    prop = lower(varargin{i});
    switch prop
        case 'parent',  parent = varargin{i+1};
        case 'range',  range = varargin{i+1};
        case {'val', 'value'},  val = varargin{i+1};
        case {'cb', 'callback'},  cb = varargin{i+1};
        case 'units',  units = varargin{i+1};
        case 'intflag',  intFlag = varargin{i+1};
        case 'flexflag',  flexFlag = varargin{i+1};
        case 'sigfigs',  sigFigs = varargin{i+1};
        case 'maxlabelflag',  maxLabelFlag = varargin{i+1};
        case 'color',  color = varargin{i+1};
		case 'fontname',  fontName = varargin{i+1};
		case 'fontsize',  fontSize = varargin{i+1};
		case 'sliderstep', sliderStep = varargin{i+1};
        case 'visible',  visible = varargin{i+1};
        otherwise,  fprintf('mrvSlider: %s unrecognized property.\n', prop);
    end
end

% default initial val
if ~exist('val', 'var') | isempty(val),  val = range(1);   end

% default initial val
if ~exist('color', 'var')|isempty(color),
    if isequal(get(parent, 'Type'), 'figure')
        color = get(parent, 'Color');
    else
        color = get(parent, 'BackgroundColor');
    end
end

% range check
if range(2)<=range(1),     range(2) = range(1)+eps;         end

if flexFlag % overrides input ranges if flexFlag
    range(1) = min([range(1), val]);
    range(2) = max([range(2), val]);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Make slider
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Slider callback string :
sliderCb = 'val = get(gcbo, ''Value'');';
if intFlag==1
	sliderCb = [sliderCb ' val = round(val); '];
end
sliderCb = sprintf('%s \n slider = get(gcbo, ''UserData'');', sliderCb);
sliderCb = sprintf('%s \n mrvSliderSet(slider, ''Val'', val);', sliderCb);
if ~isempty(cb)
    sliderCb = sprintf('%s \n %s;', sliderCb, cb);
end
sliderCb = sprintf('%s \n clear val slider; ', sliderCb);

% slider position within box
sliderPos = pos;
sliderPos(2) = pos(2) + 0.5*pos(4);
sliderPos(4) = 0.5*pos(4);

% create slider control
sliderHandle = uicontrol('Style', 'slider', ...
                        'Parent', parent, ...
                        'Units', units, ...
                        'Position', sliderPos, ...
                        'fontName', fontName, ...
						'FontSize', fontSize, ...
                        'ForegroundColor', color, ...
                        'BackgroundColor', [1 1 1], ...
                        'Min', range(1), ...
                        'Max', range(2), ...
                        'Val', val, ...
                        'SliderStep', sliderStep, ...
						'Visible', visible, ...
                        'Callback', sliderCb);
if intFlag==1
    %% make slider step across integer values
	sigFigs = 0;
	sliderStep = [.03 .15];

    if diff(range)>=1
		denom = max(1, abs(diff(range)));
        sliderStep(1) = 1/ denom; % should always page 1
	end

    set(sliderHandle, 'SliderStep', sliderStep);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% if selected,  add a little label for the max slider val
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if maxLabelFlag==1
    sliderPos(3) = sliderPos(3) * 0.8;
    set(sliderHandle, 'Position', sliderPos);
    maxLabelPos = sliderPos;
    maxLabelPos(1) = sliderPos(1) + sliderPos(3);
    maxLabelPos(3) = sliderPos(3) * 0.2/0.8;
	maxTxt = sprintf( sprintf('%%.%if', sigFigs), range(2) );
    maxLabelHandle = uicontrol('Style', 'text', ...
                        'Parent', parent, ...
                        'fontName', fontName, ...
                        'FontSize', fontSize-2, ...
                        'Units', units, ...
                        'Position', maxLabelPos, ...
                        'BackgroundColor', 'w', ...
                        'Visible', visible, ...
                        'HorizontalAlignment', 'left', ...
                        'String', maxTxt);
else
    maxLabelHandle = [];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Create text label
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% label pos within box
labelPos = pos;
labelPos(3) = 0.7*pos(3);
labelPos(4) = 0.5*pos(4);

% Create a text label w/ the slider name
labelHandle = uicontrol('Style', 'text', ...
                        'Parent', parent, ...
                        'fontName', fontName, ...
                        'FontSize', fontSize, ...
                        'Units', units, ...
                        'Position', labelPos, ...
                        'BackgroundColor', color, ...
                        'Visible', visible, ...
                        'HorizontalAlignment', 'left', ...
                        'String', [name ':']);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Create edit field
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% edit pos within box
editPos = pos;
editPos(1) = pos(1) + 0.5*pos(3);
editPos(3) = 0.5*pos(3);
editPos(4) = 0.5*pos(4);

% Edit field callback string:
editCb = 'val = str2num(get(gcbo, ''String''));';
if intFlag==1
	editCb = [editCb ' val = round(val); '];
end
editCb = sprintf('%s \n slider = get(gcbo, ''UserData'');', editCb);
editCb = sprintf('%s \n mrvSliderSet(slider, ''Val'', val);', editCb);
if ~isempty(cb)
    editCb = sprintf('%s \n %s;', editCb, cb);
end
editCb = sprintf('%s \n clear val slider;', editCb);

% make edit control
editHandle = uicontrol('Style', 'edit', ...
                        'Parent', parent, ...
                        'Units', units, ...
                        'fontName', fontName, ...
                        'FontSize', fontSize, ...
                        'Position', editPos, ...
                        'String', num2str(val), ...
                        'Visible', visible, ...
                        'BackgroundColor', color, ...
                        'Callback', editCb);

% add handles to struct
slider.name = name;
slider.sliderHandle = sliderHandle;
slider.editHandle = editHandle;
slider.labelHandle = labelHandle;
slider.maxLabelHandle = maxLabelHandle;
slider.range = range;
slider.intFlag = intFlag;
slider.flexFlag = flexFlag;
slider.sigFigs = sigFigs;
slider.maxLabelFlag = maxLabelFlag;
slider.sliderCb = sliderCb;
slider.editCb = editCb;

% set as user data to controls
set(editHandle, 'UserData', slider);
set(sliderHandle, 'UserData', slider);

return


%Detection the blueprint for Detection objects in GISMO
% An Detection object is a container for sta/lta detection metadata
% See also Arrival, Catalog
classdef Detection
    properties
        channelinfo
        time
        state
        filterString
        signal2noise
        traveltime
    end
    properties(Dependent)
        numel
    end
    methods
        function obj = Detection(sta, chan, time, state, filterString, signal2noise)

            % Blank constructor
            if ~exist('sta','var')
                return
            end

            % Parse required, optional and param-value pair arguments,
            % set default values, and add validation conditions
            p = inputParser;
            p.addRequired('sta', @iscell);
            p.addRequired('chan', @iscell);
            %p.addRequired('time', @(t) t>0 & t<now+1);
            p.addRequired('time', @isnumeric);
            p.addOptional('state', {}, @iscell);
            p.addOptional('filterString', {}, @iscell);
            p.addOptional('signal2noise', [], @isnumeric);

            % Missed several properties out here just because of laziness.
            % Add them as needed.
            p.parse(sta, chan, time, state, filterString, signal2noise);
            ctag = ChannelTag.array('',p.Results.sta,'',p.Results.chan)';
            obj.channelinfo = ctag.string();
            obj.time = p.Results.time;
            obj.state = p.Results.state;
            obj.filterString = p.Results.filterString;
            obj.signal2noise = p.Results.signal2noise;
            N = numel(obj.time);
            fprintf('\nGot %d detections\n',N);
            if numel(obj.state) == 0
                obj.state = repmat({''},1,N);
            end
            if numel(obj.filterString) == 0
                obj.filterString = repmat({''},1,N);
            end
            if numel(obj.signal2noise) == 0
                obj.signal2noise = repmat({''},1,N);
            end
            if numel(obj.traveltime) == 0
                obj.traveltime = repmat(NaN,1,N);
            end

        end

        function val = get.time(obj)
            val = obj.time;
        end

        function val = get.numel(obj)
            val = numel(obj.time);
        end

%         function val = get.channelinfo(obj)
%             val = obj.channelinfo;
%         end
%
%         function val = get.iphase(obj)
%             val = obj.iphase;
%         end
%
%         function val = get.amp(obj)
%             val = obj.amp;
%         end
%
%         function val = get.signal2noise(obj)
%             val = obj.signal2noise;
%         end
%
%         function obj = set.amp(obj, amp)
%             obj.amp = amp;
%         end

        function plot(obj)
            ctaguniq = unique(obj.channelinfo)
            N = numel(ctaguniq);
            hf1=figure;
            suptitle('Cumulative detections vs time')
            hf2=figure;
            suptitle('Percentage of detections captured by signal2noise')
            disp(sprintf('Detections: %d',numel(obj.time)))
            for c=1:N
               indexes = find(strcmp(obj.channelinfo,ctaguniq{c})==1);
%                size(indexes)
%                indexes(1:10)
               figure(hf1)
               %subplot(N,1,c);
               hold on
               t = obj.time(indexes);
               y = cumsum(ones(size(t)));
plot(t,y,'LineWidth',5);
               %ylabel(ctaguniq{c});
               ylabel(sprintf('Cumulative #\nDetections'))
               xlabel('Date/Time')
               datetick('x')
               set(gca,'XLim',[min(obj.time) max(obj.time)]);
               disp(sprintf('- %s: %d',ctaguniq{c},length(indexes==1)));

               figure(hf2)
               %subplot(N,1,c);
               hold on
               s = obj.signal2noise(indexes);
               s(s>101)=101;
               [n x]=hist(s, 1:0.1:100);
plot(x,100-cumsum(n)/sum(n)*100,'LineWidth',5);
               xlabel('signal2noise');
               %ylabel(ctaguniq{c});
               ylabel('%age')
               set(gca, 'XLim', [2.4 20]);
            end
            figure(hf1)
            legend(ctaguniq)
            figure(hf2)
            legend(ctaguniq)
        end

        function summary(obj, showall)
        % DETECTION.SUMMARY Summarise Detection object
            for c=1:numel(obj)
                obj(c)
                numrows = numel(obj(c).time);
                fprintf('Number of detections: %d\n',numrows);
                if numrows > 0
                    if ~exist('showall','var')
                            showall = false;
                    end
                    if numel(obj) == 1
                        if numrows <= 50 || showall
                            for rownum=1:numrows
                                summarize_row(obj, rownum);
                            end
                        else
                            for rownum=1:50
                                summarize_row(obj, rownum);
                            end
                            disp('* Only showing first 50 rows/arrivals - to see all rows/arrivals use:')
                            disp('*      arrivalObject.disp(true)')
                        end
                    end
                end
            end
        end

        function summarize_row(self, rownum)
            fprintf('%s\t%s\t%s\t%e\n', ...
                self.channelinfo(rownum), ...
                datestr(self.time(rownum)), ...
                self.state(rownum), ...
                self.signal2noise(rownum));
        end

        function self2 = subset(self, columnname, findval)
            self2 = self;
            N = numel(self.time);
            indexes = [];
            if ~exist('findval','var')
                % assume columnname is actually row numbers
                indexes = columnname;
            else

                for c=1:N
                    gotval = eval(sprintf('self.%s(c);',columnname));
                    if isa(gotval,'cell')
                        gotval = cell2mat(gotval);
                    end
                    if isnumeric(gotval)
                        if gotval==findval
                            indexes = [indexes c];
                        end
                    else
                        if strcmp(gotval,findval)
                            indexes = [indexes c];
                        end
                    end
                end
            end
%             if isa(self.channelinfo,'cell')
%                 self2.channelinfo = self.channelinfo{indexes};
%             else
                 self2.channelinfo = self.channelinfo(indexes);
%             end
            self2.time = self.time(indexes);
            self2.state = self.state(indexes);
            if numel(self.filterString)==N
                self2.filterString = self.filterString(indexes);
            end
            if numel(self.signal2noise)==N
                self2.signal2noise = self.signal2noise(indexes);
            end
            if numel(self.traveltime)==N
                self2.traveltime = self.traveltime(indexes);
            end
        end

        function self = append(self1, self2)
            disp('Appending...')
            [newtime, indices] = sort([self1.time self2.time]);
            size(cellstr(self1.channelinfo))
            size(cellstr(self2.channelinfo))
            newchannelinfo = [cellstr(self1.channelinfo); cellstr(self2.channelinfo)];
            newchannelinfo = newchannelinfo(indices);
            newstate = [cellstr(self1.state); cellstr(self2.state)];
            newstate = newstate(indices);
            newfs = [cellstr(self1.filterString); cellstr(self2.filterString)];
            newfs = newfs(indices);
            newsnr = [self1.signal2noise self2.signal2noise];
            newsnr = newsnr(indices);
            ctags = ChannelTag(newchannelinfo);
            %self = Detection(cellstr([get(ctags,'station')]), cellstr([get(ctags,'channel')]), newtime, cellstr([newstate]), cellstr([newfs]), newsnr)
            self = Detection([get(ctags,'station')], ...
                [get(ctags,'channel')], ...
                newtime, ...
                newstate, ...
                [newfs], ...
                newsnr)
        end

        % prototypes
         catalogobj = associate(self, maxTimeDiff, sites, source)
%         write(detectionobj, FORMAT, PATH);
    end
    methods(Static)
        function self = retrieve(dbname, subset_expr)
        %DETECTION.RETRIEVE Read detections from an Antelope CSS3.0 table
        %
        % Usage:
        %       detectionObj = DETECTION.RETRIEVE(dbname, subset_expr)

        % Author: Glenn Thompson (glennthompson1971@gmail.com)

            debug.printfunctionstack('>')
            self = [];
            if ~(antelope.dbtable_present(dbname, 'detection'))
                fprintf('No detection table belonging to %s\n',dbname);
                return
            end

            fprintf('Loading detections from %s\n',dbname);

            % Open database
            db = dbopen(dbname,'r');
            disp('- database opened');

            % Apply subset expression
            db = dblookup_table(db,'detection');
            disp('- detection table opened');
            if exist('subset_expr','var')
                db = dbsubset(db,subset_expr);
                disp('- subsetted database')
            end

            nrows = dbnrecs(db);
            if nrows > 0

                % Sort by arrival time
                db = dbsort(db,'time');
                disp('- sorted detection table')

                % Get the values
                fprintf('- reading %d rows\n',nrows);
                [sta,chan,time,state,filterString,signal2noise] = dbgetv(db,'sta','chan','time','state', 'filter','snr');

                % Close database link
                dbclose(db);
                disp('- database closed')

                % Create detection object
                disp('- creating detection object')
                self = Detection(cellstr(sta), cellstr(chan), epoch2datenum(time), cellstr(state), cellstr(filterString), signal2noise);

                disp('- complete!')
            else
                fprintf('No detections found matching request\n');
            end

            debug.printfunctionstack('<')
        end

        %cookbook()
    end
end


function [c, r, t, cpulse, verbose] = ...
    tapas_physio_read_physlogfiles_siemens(log_files, cardiac_modality, verbose, varargin)
% reads out physiological time series and timing vector for Siemens
% logfiles of peripheral cardiac monitoring (ECG/Breathing Belt or
% pulse oximetry)
%
%   [cpulse, rpulse, t, c] = tapas_physio_read_physlogfiles_siemens(...
%           logfile, vendor, cardiac_modality)
%
% IN    log_files
%       .log_cardiac        contains ECG or pulse oximeter time course
%                           for GE: ECGData...
%       .log_respiration    contains breathing belt amplitude time course
%                           for GE: RespData...
%       cardiac_modality    'ECG' or 'PULS'/'PPU'/'OXY' to determine
%                           which channel data to be returned
%                           if not given, will be read out from file name
%                           suffix
%       verbose
%       .level              debugging plots are created if level >=3
%       .fig_handles        appended by handle to output figure
%
%       varargin            propertyName/value pairs, as folloes
%           'ecgChannel'    'v1', 'v2', 'mean' (default)
%                           determines which ECG channel to use as
%                           output cardiac curve
%           'sqpar'         sqpar, needed for scan_align to 'last' volume
%                           of a run
%
% OUT
%   cpulse              time events of R-wave peak in cardiac time series (seconds)
%                       for GE: usually empty
%   r                   respiratory time series
%   t                   vector of time points (in seconds)
%                       NOTE: This assumes the default sampling rate of 40
%                       Hz
%   c                   cardiac time series (ECG or pulse oximetry)
%
% EXAMPLE
%   [ons_secs.cpulse, ons_secs.rpulse, ons_secs.t, ons_secs.c] =
%       tapas_physio_read_physlogfiles_siemens(logfile, vendor, cardiac_modality);
%
%   See also tapas_physio_main_create_regressors

% Author: Lars Kasper
%         file structure information from PhLeM Toolbox, T. Verstynen (November 2007);
%                and Deshpande and J. Grinstead, Siemens Medical Solutions (March 2009)
%         additional log information Miriam Sebold, Charite Berlin (2014)
%
% Created: 2014-07-08
% Copyright (C) 2014 Institute for Biomedical Engineering, ETH/Uni Zurich.
%
% This file is part of the PhysIO toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

%% read out values

if nargin < 3
    verbose.level = 0;
end
DEBUG = verbose.level >=2;

% process optional input parameters and overwrite defaults
defaults.sqpar = [];
defaults.endCropSeconds     = 1;
% used channel depends on cardiac modality
switch cardiac_modality
    case 'ECG'
        defaults.ecgChannel = 'mean'; %'mean'; 'v1'; 'v2'
    otherwise
        defaults.ecgChannel = 'v1';
end

args = tapas_physio_propval(varargin, defaults);
tapas_physio_strip_fields(args);

cpulse              = [];

dt                  = log_files.sampling_interval;

explicit_relative_start_acquisition = log_files.relative_start_acquisition;

if isempty(explicit_relative_start_acquisition)
    explicit_relative_start_acquisition = 0;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Determine relative start of acquisition from dicom headers and
% logfile footers
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

hasScanTimingDicomImage = ~isempty(log_files.scan_timing);
hasCardiacData = ~isempty(log_files.cardiac);
hasRespData = ~isempty(log_files.respiration);

if hasScanTimingDicomImage
    % Times are in seconds since start of the day

    dicomHeader             = spm_dicom_headers(...
        fullfile(log_files.scan_timing));

    try % old example DICOM format
        tStartScanDicom    = dicomHeader{1}.AcquisitionTime;

        TR = dicomHeader{1}.RepetitionTime/1000;

        % TODO: Include AcquisitionNumber? InstanceNumber?

    catch % new XA30 DICOM export
        dc = dicomHeader{1};

        % tried different fields, Study/SeriesTime refer to 1st volume
        % ContentTime > InstanceCreationTime > dc.AcquisitionDateTime
        % difference is about one second each
        % (1.14 and 0.89s for vol 250, 1.35 and 1.97s for vol 001, TR was 1.2s)
        % Since naming was most similar to AcquisitionDateTime, we chose
        % that one...
        % parse Date/Time format from Dicom field, and reformat it as
        % seconds since start of day
        dateVector = datevec(dc.AcquisitionDateTime, 'yyyymmddHHMMSS.FFF');
        tStartScanDicom = dateVector(end-2:end)*[3600 60 1]';
        TR = dc.SharedFunctionalGroupsSequence{1}.MRTimingAndRelatedParametersSequence{1}.RepetitionTime/1000;

    end

    tStopScanDicom     = tStartScanDicom + TR;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Read in cardiac data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if hasCardiacData

    [lineData, logFooter] = tapas_physio_read_physlogfiles_siemens_raw(...
        log_files.cardiac);
    tLogTotal = logFooter.LogStopTimeSeconds - logFooter.LogStartTimeSeconds;

    if hasScanTimingDicomImage
        tStartScan = tStartScanDicom; % this is just the start of the selected DICOM volume
        tStopScan = tStopScanDicom;
    else
        % Just different time scale, gives bad scaling in plots, and not
        % needed...
        %     tStartScan = logFooter.ScanStartTimeSeconds;
        %     tStopScan = logFooter.ScanStopTimeSeconds;
        tStartScan = logFooter.LogStartTimeSeconds;
        tStopScan = logFooter.LogStopTimeSeconds;
    end

    switch log_files.align_scan
        case 'first'
            relative_start_acquisition = tStartScan ...
                - logFooter.LogStartTimeSeconds;
        case 'last'
            % shift onset of first scan by knowledge of run duration and
            % onset of last scan in run
            relative_start_acquisition = ...
                (tStopScan - sqpar.Nscans*sqpar.TR) ...
                - logFooter.LogStartTimeSeconds;
    end

    % add arbitrary offset specified by user
    relative_start_acquisition = relative_start_acquisition + ...
        explicit_relative_start_acquisition;

    data_table = tapas_physio_siemens_line2table(lineData, cardiac_modality);

    if isempty(dt)
        nSamplesC = size(data_table,1);
        dt_c = tLogTotal/(nSamplesC-1);
    else
        dt_c = dt(1);
    end

    dataCardiac = tapas_physio_siemens_table2cardiac(data_table, ecgChannel, dt_c, ...
        relative_start_acquisition, endCropSeconds);

    if DEBUG
        verbose.fig_handles(end+1) = ...
            tapas_physio_plot_raw_physdata_siemens(dataCardiac);
    end

    %% crop end of log file
    cpulse = dataCardiac.cpulse_on;
    c = dataCardiac.c;
    t_c = dataCardiac.t;
    stopSample = dataCardiac.stopSample;

    cpulse(cpulse > t_c(dataCardiac.stopSample)) = [];
    t_c(stopSample+1:end) = [];
    c(stopSample+1:end) = [];

else
    c = [];
    t_c = [];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Read in respiratory data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if hasRespData
    [lineData, logFooter] = tapas_physio_read_physlogfiles_siemens_raw(...
        log_files.respiration);
    tLogTotal = logFooter.LogStopTimeSeconds - logFooter.LogStartTimeSeconds;

    if hasScanTimingDicomImage
        tStartScan = tStartScanDicom;
        tStopScan = tStopScanDicom; % is incorrect, use tStartScan + TR!
    else
        % Just different time scale, gives bad scaling in plots, and not
        % needed...
        %     tStartScan = logFooter.ScanStartTimeSeconds;
        %     tStopScan = logFooter.ScanStopTimeSeconds;
        tStartScan = logFooter.LogStartTimeSeconds;
        tStopScan = logFooter.LogStopTimeSeconds;
    end

    switch log_files.align_scan
        case 'first'
            relative_start_acquisition = tStartScan - ...
                logFooter.LogStartTimeSeconds;
        case 'last'
            % shift onset of first scan by knowledge of run duration and
            % onset of last scan in run
            relative_start_acquisition = ...
                (tStartScan - (sqpar.Nscans-1)*sqpar.TR) ...
                - logFooter.LogStartTimeSeconds;
    end

    % add arbitrary offset specified by user
    relative_start_acquisition = relative_start_acquisition + ...
        explicit_relative_start_acquisition;

    data_table = tapas_physio_siemens_line2table(lineData, 'RESP');

    if isempty(dt)
        nSamplesR = size(data_table,1);
        dt_r = tLogTotal/(nSamplesR-1);
    else
        dt_r = dt(end);
    end

    dataResp = tapas_physio_siemens_table2cardiac(data_table, ecgChannel, ...
        dt_r, relative_start_acquisition, endCropSeconds);

    if DEBUG
        verbose.fig_handles(end+1) = ...
            tapas_physio_plot_raw_physdata_siemens(dataResp);
    end

    r = dataResp.c;
    t_r = dataResp.t;

    %
    %% crop end of log file???
    % stopSample = dataResp.stopSample;
    % t(stopSample+1:end) = [];
    % c(stopSample+1:end) = [];

else
    r = [];
    t_r = [];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Adapt time scales resp/cardiac, i.e. zero fill c or r
% to get equal length with max(c_t, r_t)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

nSamplesR = numel(r);
nSamplesC = numel(c);

if  nSamplesR > nSamplesC
    t = t_r; % time scale defined by respiration now, since longer
    if nSamplesC > 0 % zero-fill cardiac data
        c(nSamplesC+1:nSamplesR) = 0;
    end
else
    t = t_c;
    if nSamplesR > 0
        r(nSamplesR+1:nSamplesC) = 0;
    end
end

end


function r = eq(p,q)
% this function compares the equality condition of x, y, and z values of the structures that I use in
% the FVtool.
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Copyright (c) 2012-2016 Ali Akbar Eftekhari
% See the license file

if (isa(p, 'FaceVariable')&&isa(q, 'FaceVariable'))
    r=p;
    r.xvalue = p.xvalue==q.xvalue;
    r.yvalue = p.yvalue==q.yvalue;
    r.zvalue = p.zvalue==q.zvalue;
elseif isa(p, 'FaceVariable')
    r=p;
    r.xvalue = p.xvalue==q;
    r.yvalue = p.yvalue==q;
    r.zvalue = p.zvalue==q;
else
    r=q;
    r.xvalue = p==q.xvalue;
    r.yvalue = p==q.yvalue;
    r.zvalue = p==q.zvalue;
end


function candoit = canGetApproxHessian(problem)
% Checks whether an approximate Hessian can be computed for this problem.
%
% function candoit = canGetApproxHessian(problem)
%
% Returns true if an approximate Hessian of the cost function is provided
% in the given problem description, false otherwise.
% If a Hessian is defined but no approximate Hessian is defined explicitly,
% returns false.
%
% Even if this returns false, calls to getApproxHessian may succeed, as
% they will be redirected to getHessianFD. The latter simply requires
% availability of gradients in problem, and vector transports in problem.M.
%
% See also: canGetHessian getHessianFD

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, April 8, 2015.
% Contributors:
% Change log:

    candoit = isfield(problem, 'approxhess');

end


%% REW_gym
% %{
imfolder = 'images\REW_gym';
im_n = 2;
imfile = cell(im_n,1);
imfile{1} = [imfolder '\' 'gym_01.jpg'];
imfile{2} = [imfolder '\' 'gym_02.jpg'];

im = cell(im_n,1);
for ii = 1:im_n
    im{ii} = imread(imfile{ii});
end

edge_list = [1,2];

% imsize = zeros(im_n,3);
%
% for ii = 1:im_n
%     imsize(ii,:) = size(im{ii});
%     if imsize(ii,1) > 720
%         scale = 720/size(im{ii}, 1);
%         im{ii} = imresize(im{ii}, scale);
%
%         imsize(ii,:) = size(im{ii});
%     end
% end

mosaic = REW_mosaic( im, edge_list, 1, 'persp', 0, imfolder );
%}


function t_ext2int2ext(quiet)
%T_EXT2INT2EXT  Tests EXT2INT, INT2EXT, and related functions.
%   Includes tests for GET_REORDER, SET_REORDER, E2I_DATA, I2E_DATA
%   E2I_FIELD, I2E_FIELD, EXT2INT and INT2EXT.

%   MATPOWER
%   Copyright (c) 2009-2016, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

if nargin < 1
    quiet = 0;
end

num_tests = 165;
t_begin(num_tests, quiet);

%% define named indices into data matrices
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
    VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;

%% for MATLAB versions prior to R2012a (v 7.14)
if ~exist('isequaln')
    eval('isequaln = @isequalwithequalnans;');
end

if have_feature('matlab', 'vnum') < 7.001
    t_skip(num_tests, 'test requires cellfun() construct not available before MATLAB 7.1');
else
    mpce = loadcase('t_case_ext');
    mpce = add_userfcn(mpce, 'ext2int', @userfcn_test_ext2int);
    mpce = add_userfcn(mpce, 'int2ext', @userfcn_test_int2ext);
    mpci = loadcase('t_case_int');

    gen_i2e = [1 2 4];

    An = mpce.xbus;
    As = mpce.strbus;

    %%-----  get_reorder  -----
    k = [3; 7; 4; 1];
    t = 'get_reorder(A, k, 1) : numeric';
    t_is(get_reorder(An, k, 1), An(k, :), 12, t);

    t = 'get_reorder(A, k, 2) : numeric';
    t_is(get_reorder(An, k, 2), An(:, k), 12, t);

    %%-----  set_reorder  -----
    k = (2:2:10)';
    t = 'set_reorder(A, B, k, 1) : numeric';
    B = An(k, :) * -1;
    got = set_reorder(An, B, k, 1);
    ex = An;
    ex(k, :) = -ex(k, :);
    t_is(got, ex, 12, t);

    t = 'set_reorder(A, B, k, 2) : numeric';
    B = An(:, k) * -1;
    got = set_reorder(An, B, k, 2);
    ex = An;
    ex(:, k) = -ex(:, k);
    t_is(got, ex, 12, t);

    t = 'set_reorder(A, Bshort, k, 1) : numeric';
    k = (2:2:8)';
    B = An(k, 1:8) * -1;
    got = set_reorder(An, B, k, 1);
    ex = An;
    ex(k, 1:8) = -ex(k, 1:8);
    t_is(got, ex, 12, t);

    t = 'set_reorder(A, Bshort, k, 2) : numeric';
    B = An(1:8, k) * -1;
    got = set_reorder(An, B, k, 2);
    ex = An;
    ex(1:8, k) = -ex(1:8, k);
    t_is(got, ex, 12, t);

    t = 'set_reorder(A, Blong, k, 1) : numeric';
    k = (2:2:10)';
    B = An(k, :) * -1;
    B = [B B];
    got = set_reorder(An, B, k, 1);
    ex = [An zeros(size(An))];
    ex(k, :) = [-An(k, :) -An(k, :)];
    t_is(got, ex, 12, t);

    t = 'set_reorder(A, Blong, k, 2) : numeric';
    B = An(:, k) * -1;
    B = [B; B];
    got = set_reorder(An, B, k, 2);
    ex = [An; zeros(size(An))];
    ex(:, k) = [-An(:, k); -An(:, k)];
    t_is(got, ex, 12, t);

    %%-----  get_reorder (cell)  -----
    k = [3; 7; 4; 1];
    t = 'get_reorder(A, k, 1) : cell';
    t_is(cellfun(@str2num, get_reorder(As, k, 1)), cellfun(@str2num, As(k, :)), 12, t);

    t = 'get_reorder(A, k, 2) : cell';
    t_is(cellfun(@str2num, get_reorder(As, k, 2)), cellfun(@str2num, As(:, k)), 12, t);

    %%-----  set_reorder (cell)  -----
    k = (2:2:10)';
    t = 'set_reorder(A, B, k, 1) : cell';
    B = cellfun(@num2str, num2cell(An(k, :) * -1), 'UniformOutput', 0);
    got = set_reorder(As, B, k, 1);
    ex = As;
    ex(k, :) = cellfun(@num2str, num2cell(-cellfun(@str2num, ex(k, :))), 'UniformOutput', 0);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    t = 'set_reorder(A, B, k, 2) : cell';
    B = cellfun(@num2str, num2cell(An(:, k) * -1), 'UniformOutput', 0);
    got = set_reorder(As, B, k, 2);
    ex = As;
    ex(:, k) = cellfun(@num2str, num2cell(-cellfun(@str2num, ex(:, k))), 'UniformOutput', 0);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    t = 'set_reorder(A, Bshort, k, 1) : cell';
    k = (2:2:8)';
    B = cellfun(@num2str, num2cell(An(k, 1:8) * -1), 'UniformOutput', 0);
    got = set_reorder(As, B, k, 1);
    ex = As;
    ex(k, 1:8) = cellfun(@num2str, num2cell(-cellfun(@str2num, ex(k, 1:8))), 'UniformOutput', 0);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    t = 'set_reorder(A, Bshort, k, 2) : cell';
    B = cellfun(@num2str, num2cell(An(1:8, k) * -1), 'UniformOutput', 0);
    got = set_reorder(As, B, k, 2);
    ex = As;
    ex(1:8, k) = cellfun(@num2str, num2cell(-cellfun(@str2num, ex(1:8, k))), 'UniformOutput', 0);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    t = 'set_reorder(A, Blong, k, 1) : cell';
    k = (2:2:10)';
    B = cellfun(@num2str, num2cell(An(k, :) * -1), 'UniformOutput', 0);
    B = [B B];
    got = set_reorder(As, B, k, 1);
    ex = [As cell(size(As))];
    ex(k, :) = cellfun(@num2str, num2cell([-An(k, :) -An(k, :)]), 'UniformOutput', 0);
    for i = 1:size(got, 1)      %% replace [] with '-999' to make str2num happy
        for j = 1:size(got, 2)
            if isempty(got{i, j})
                got{i, j} = '-999';
            end
            if isempty(ex{i, j})
                ex{i, j} = '-999';
            end
        end
    end
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    t = 'set_reorder(A, Blong, k, 2) : cell';
    B = cellfun(@num2str, num2cell(An(:, k) * -1), 'UniformOutput', 0);
    B = [B; B];
    got = set_reorder(As, B, k, 2);
    ex = [As; cell(size(As))];
    ex(:, k) = cellfun(@num2str, num2cell([-An(:, k); -An(:, k)]), 'UniformOutput', 0);
    for i = 1:size(got, 1)      %% replace [] with '-999' to make str2num happy
        for j = 1:size(got, 2)
            if isempty(got{i, j})
                got{i, j} = '-999';
            end
            if isempty(ex{i, j})
                ex{i, j} = '-999';
            end
        end
    end
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);

    %%-----  mpc = ext2int/int2ext(mpc)  -----
    t = 'mpc = ext2int(mpc) : ';
    mpc = ext2int(mpce);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpci.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpci.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpci.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);
    t_is(mpc.N, mpci.N, 12, [t 'N']);
    t = 'mpc = ext2int(mpc) - repeat : ';
    mpc = ext2int(mpc);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpci.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpci.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpci.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);
    t_is(mpc.N, mpci.N, 12, [t 'N']);
    t = 'mpc = int2ext(mpc) : ';
    mpc = int2ext(mpc);
    t_is(mpc.bus, mpce.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpce.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpce.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpce.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpce.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpce.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpce.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpce.A, 12, [t 'A']);
    t_is(mpc.N, mpce.N, 12, [t 'N']);

    %%-----  mpc = ext2int/int2ext(mpc, mpopt)  -----
    mpopt = mpoption();
    t = 'mpc = ext2int(mpc, mpopt) : ';
    mpc = ext2int(mpce, mpopt);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpci.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpci.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpci.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);
    t_is(mpc.N, mpci.N, 12, [t 'N']);
    t = 'mpc = ext2int(mpc, mpopt) - repeat : ';
    mpc = ext2int(mpc, mpopt);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpci.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpci.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpci.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);
    t_is(mpc.N, mpci.N, 12, [t 'N']);
    t = 'mpc = int2ext(mpc, mpopt) : ';
    mpc = int2ext(mpc, mpopt);
    t_is(mpc.bus, mpce.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpce.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpce.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpce.gencost, 12, [t 'gencost']);
    t_ok(isequaln(mpc.bus_name, mpce.bus_name), [t 'bus_name']);
    t_ok(isequaln(mpc.gentype, mpce.gentype), [t 'gentype']);
    t_ok(isequaln(mpc.genfuel, mpce.genfuel), [t 'genfuel']);
    t_is(mpc.A, mpce.A, 12, [t 'A']);
    t_is(mpc.N, mpce.N, 12, [t 'N']);

    %%-----  val = e2i_data/i2e_data(mpc, val, ...)  -----
    t = 'val = e2i_data(mpc, val, ''bus'')';
    mpc = ext2int(mpce);
    got = e2i_data(mpc, mpce.xbus, 'bus');
    ex = mpce.xbus;
    ex(6, :) = [];
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''bus'')';
    tmp = ones(size(mpce.xbus));
    tmp(6, :) = mpce.xbus(6, :);
    got = i2e_data(mpc, ex, tmp, 'bus');
    t_is(got, mpce.xbus, 12, t);

    t = 'val = e2i_data(mpc, val, ''bus'', 2)';
    got = e2i_data(mpc, mpce.xbus, 'bus', 2);
    ex = mpce.xbus;
    ex(:, 6) = [];
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''bus'', 2)';
    tmp = ones(size(mpce.xbus));
    tmp(:, 6) = mpce.xbus(:, 6);
    got = i2e_data(mpc, ex, tmp, 'bus', 2);
    t_is(got, mpce.xbus, 12, t);

    t = 'val = e2i_data(mpc, val, ''gen'')';
    got = e2i_data(mpc, mpce.xgen, 'gen');
    ex = mpce.xgen(gen_i2e, :);
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''gen'')';
    tmp = ones(size(mpce.xgen));
    tmp(3, :) = mpce.xgen(3, :);
    got = i2e_data(mpc, ex, tmp, 'gen');
    t_is(got, mpce.xgen, 12, t);

    t = 'val = e2i_data(mpc, val, ''gen'', 2)';
    got = e2i_data(mpc, mpce.xgen, 'gen', 2);
    ex = mpce.xgen(:, gen_i2e);
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''gen'', 2)';
    tmp = ones(size(mpce.xgen));
    tmp(:, 3) = mpce.xgen(:, 3);
    got = i2e_data(mpc, ex, tmp, 'gen', 2);
    t_is(got, mpce.xgen, 12, t);

    t = 'val = e2i_data(mpc, val, ''branch'')';
    got = e2i_data(mpc, mpce.xbranch, 'branch');
    ex = mpce.xbranch;
    ex(7, :) = [];
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''branch'')';
    tmp = ones(size(mpce.xbranch));
    tmp(7, :) = mpce.xbranch(7, :);
    got = i2e_data(mpc, ex, tmp, 'branch');
    t_is(got, mpce.xbranch, 12, t);

    t = 'val = e2i_data(mpc, val, ''branch'', 2)';
    got = e2i_data(mpc, mpce.xbranch, 'branch', 2);
    ex = mpce.xbranch;
    ex(:, 7) = [];
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, ''branch'', 2)';
    tmp = ones(size(mpce.xbranch));
    tmp(:, 7) = mpce.xbranch(:, 7);
    got = i2e_data(mpc, ex, tmp, 'branch', 2);
    t_is(got, mpce.xbranch, 12, t);

    t = 'val = e2i_data(mpc, val, {''branch'', ''gen'', ''bus''})';
    got = e2i_data(mpc, mpce.xrows, {'branch', 'gen', 'bus'});
    ex = [mpce.xbranch([1:6, 8:10], 1:4); mpce.xgen(gen_i2e, :); mpce.xbus([1:5, 7:10], 1:4); -ones(2, 4)];
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, {''branch'', ''gen'', ''bus''})';
    tmp1 = ones(size(mpce.xbranch(:, 1:4)));
    tmp1(7, 1:4) = mpce.xbranch(7, 1:4);
    tmp2 = ones(size(mpce.xgen));
    tmp2(3, :) = mpce.xgen(3, :);
    tmp3 = ones(size(mpce.xbus(:, 1:4)));
    tmp3(6, 1:4) = mpce.xbus(6, 1:4);
    tmp = [tmp1; tmp2; tmp3];
    got = i2e_data(mpc, ex, tmp, {'branch', 'gen', 'bus'});
    t_is(got, mpce.xrows, 12, t);

    t = 'val = e2i_data(mpc, val, {''branch'', ''gen'', ''bus''}, 2)';
    got = e2i_data(mpc, mpce.xcols, {'branch', 'gen', 'bus'}, 2);
    ex = [mpce.xbranch([1:6, 8:10], 1:4); mpce.xgen(gen_i2e, :); mpce.xbus([1:5, 7:10], 1:4); -ones(2, 4)]';
    t_is(got, ex, 12, t);
    t = 'val = i2e_data(mpc, val, oldval, {''branch'', ''gen'', ''bus''}, 2)';
    tmp1 = ones(size(mpce.xbranch(:, 1:4)));
    tmp1(7, 1:4) = mpce.xbranch(7, 1:4);
    tmp2 = ones(size(mpce.xgen));
    tmp2(3, :) = mpce.xgen(3, :);
    tmp3 = ones(size(mpce.xbus(:, 1:4)));
    tmp3(6, 1:4) = mpce.xbus(6, 1:4);
    tmp = [tmp1; tmp2; tmp3]';
    got = i2e_data(mpc, ex, tmp, {'branch', 'gen', 'bus'}, 2);
    t_is(got, mpce.xcols, 12, t);

    %%-----  val = e2i_data/i2e_data(mpc, cell, ...)  -----
    t = 'val = e2i_data(mpc, cell, ''bus'')';
    mpc = ext2int(mpce);
    got = e2i_data(mpc, mpce.strbus, 'bus');
    ex = mpce.strbus;
    ex(6, :) = [];
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''bus'')';
    tmp = cell(size(mpce.strbus));
    tmp(6, :) = mpce.strbus(6, :);
    got = i2e_data(mpc, ex, tmp, 'bus');
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strbus), 12, t);

    t = 'val = e2i_data(mpc, cell, ''bus'', 2)';
    got = e2i_data(mpc, mpce.strbus, 'bus', 2);
    ex = mpce.strbus;
    ex(:, 6) = [];
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''bus'', 2)';
    tmp = cell(size(mpce.strbus));
    tmp(:, 6) = mpce.strbus(:, 6);
    got = i2e_data(mpc, ex, tmp, 'bus', 2);
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strbus), 12, t);

    t = 'val = e2i_data(mpc, cell, ''gen'')';
    got = e2i_data(mpc, mpce.strgen, 'gen');
    ex = mpce.strgen(gen_i2e, :);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''gen'')';
    tmp = cell(size(mpce.strgen));
    tmp(3, :) = mpce.strgen(3, :);
    got = i2e_data(mpc, ex, tmp, 'gen');
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strgen), 12, t);

    t = 'val = e2i_data(mpc, cell, ''gen'', 2)';
    got = e2i_data(mpc, mpce.strgen, 'gen', 2);
    ex = mpce.strgen(:, gen_i2e);
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''gen'', 2)';
    tmp = cell(size(mpce.strgen));
    tmp(:, 3) = mpce.strgen(:, 3);
    got = i2e_data(mpc, ex, tmp, 'gen', 2);
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strgen), 12, t);

    t = 'val = e2i_data(mpc, cell, ''branch'')';
    got = e2i_data(mpc, mpce.strbranch, 'branch');
    ex = mpce.strbranch;
    ex(7, :) = [];
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''branch'')';
    tmp = cell(size(mpce.strbranch));
    tmp(7, :) = mpce.strbranch(7, :);
    got = i2e_data(mpc, ex, tmp, 'branch');
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strbranch), 12, t);

    t = 'val = e2i_data(mpc, cell, ''branch'', 2)';
    got = e2i_data(mpc, mpce.strbranch, 'branch', 2);
    ex = mpce.strbranch;
    ex(:, 7) = [];
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, ''branch'', 2)';
    tmp = cell(size(mpce.strbranch));
    tmp(:, 7) = mpce.strbranch(:, 7);
    got = i2e_data(mpc, ex, tmp, 'branch', 2);
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strbranch), 12, t);

    t = 'val = e2i_data(mpc, cell, {''branch'', ''gen'', ''bus''})';
    got = e2i_data(mpc, mpce.strrows, {'branch', 'gen', 'bus'});
    ex = [mpce.strbranch([1:6, 8:10], 1:4); mpce.strgen(gen_i2e, :); mpce.strbus([1:5, 7:10], 1:4); cellfun(@num2str, num2cell(-ones(2, 4)), 'UniformOutput', 0)];
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, {''branch'', ''gen'', ''bus''})';
    tmp1 = cell(size(mpce.strbranch(:, 1:4)));
    tmp1(7, 1:4) = mpce.strbranch(7, 1:4);
    tmp2 = cell(size(mpce.strgen));
    tmp2(3, :) = mpce.strgen(3, :);
    tmp3 = cell(size(mpce.strbus(:, 1:4)));
    tmp3(6, 1:4) = mpce.strbus(6, 1:4);
    tmp = [tmp1; tmp2; tmp3];
    got = i2e_data(mpc, ex, tmp, {'branch', 'gen', 'bus'});
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strrows), 12, t);

    t = 'val = e2i_data(mpc, cell, {''branch'', ''gen'', ''bus''}, 2)';
    got = e2i_data(mpc, mpce.strcols, {'branch', 'gen', 'bus'}, 2);
    ex = [mpce.strbranch([1:6, 8:10], 1:4); mpce.strgen(gen_i2e, :); mpce.strbus([1:5, 7:10], 1:4); cellfun(@num2str, num2cell(-ones(2, 4)), 'UniformOutput', 0)]';
    t_is(cellfun(@str2num, got), cellfun(@str2num, ex), 12, t);
    t = 'val = i2e_data(mpc, cell, oldval, {''branch'', ''gen'', ''bus''}, 2)';
    tmp1 = cell(size(mpce.strbranch(:, 1:4)));
    tmp1(7, 1:4) = mpce.strbranch(7, 1:4);
    tmp2 = cell(size(mpce.strgen));
    tmp2(3, :) = mpce.strgen(3, :);
    tmp3 = cell(size(mpce.strbus(:, 1:4)));
    tmp3(6, 1:4) = mpce.strbus(6, 1:4);
    tmp = [tmp1; tmp2; tmp3]';
    got = i2e_data(mpc, ex, tmp, {'branch', 'gen', 'bus'}, 2);
    t_is(cellfun(@str2num, got), cellfun(@str2num, mpce.strcols), 12, t);

    %%-----  mpc = e2i_field/i2e_field(mpc, field, ...)  -----
    t = 'mpc = e2i_field(mpc, field, ''bus'')';
    mpc = ext2int(mpce);
    ex = mpce.xbus;
    ex(6, :) = [];
    got = e2i_field(mpc, 'xbus', 'bus');
    t_is(got.xbus, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''bus'')';
    got = i2e_field(got, 'xbus', 'bus');
    t_is(got.xbus, mpce.xbus, 12, t);

    t = 'mpc = e2i_field(mpc, field, ''bus'', 2)';
    ex = mpce.xbus;
    ex(:, 6) = [];
    got = e2i_field(mpc, 'xbus', 'bus', 2);
    t_is(got.xbus, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''bus'', 2)';
    got = i2e_field(got, 'xbus', 'bus', 2);
    t_is(got.xbus, mpce.xbus, 12, t);

    t = 'mpc = e2i_field(mpc, field, ''gen'')';
    ex = mpce.xgen(gen_i2e, :);
    got = e2i_field(mpc, 'xgen', 'gen');
    t_is(got.xgen, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''gen'')';
    got = i2e_field(got, 'xgen', 'gen');
    t_is(got.xgen, mpce.xgen, 12, t);

    t = 'mpc = e2i_field(mpc, field, ''gen'', 2)';
    ex = mpce.xgen(:, gen_i2e);
    got = e2i_field(mpc, 'xgen', 'gen', 2);
    t_is(got.xgen, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''gen'', 2)';
    got = i2e_field(got, 'xgen', 'gen', 2);
    t_is(got.xgen, mpce.xgen, 12, t);

    t = 'mpc = e2i_field(mpc, field, ''branch'')';
    ex = mpce.xbranch;
    ex(7, :) = [];
    got = e2i_field(mpc, 'xbranch', 'branch');
    t_is(got.xbranch, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''branch'')';
    got = i2e_field(got, 'xbranch', 'branch');
    t_is(got.xbranch, mpce.xbranch, 12, t);

    t = 'mpc = e2i_field(mpc, field, ''branch'', 2)';
    ex = mpce.xbranch;
    ex(:, 7) = [];
    got = e2i_field(mpc, 'xbranch', 'branch', 2);
    t_is(got.xbranch, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, ''branch'', 2)';
    got = i2e_field(got, 'xbranch', 'branch', 2);
    t_is(got.xbranch, mpce.xbranch, 12, t);

    t = 'mpc = e2i_field(mpc, field, {''branch'', ''gen'', ''bus''})';
    ex = [mpce.xbranch([1:6, 8:10], 1:4); mpce.xgen(gen_i2e, :); mpce.xbus([1:5, 7:10], 1:4); -ones(2, 4)];
    got = e2i_field(mpc, 'xrows', {'branch', 'gen', 'bus'});
    t_is(got.xrows, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, {''branch'', ''gen'', ''bus''})';
    got = i2e_field(got, 'xrows', {'branch', 'gen', 'bus'});
    t_is(got.xrows, mpce.xrows, 12, t);

    t = 'mpc = e2i_field(mpc, field, {''branch'', ''gen'', ''bus''}, 2)';
    ex = [mpce.xbranch([1:6, 8:10], 1:4); mpce.xgen(gen_i2e, :); mpce.xbus([1:5, 7:10], 1:4); -ones(2, 4)]';
    got = e2i_field(mpc, 'xcols', {'branch', 'gen', 'bus'}, 2);
    t_is(got.xcols, ex, 12, t);
    t = 'mpc = i2e_field(mpc, field, {''branch'', ''gen'', ''bus''})';
    got = i2e_field(got, 'xcols', {'branch', 'gen', 'bus'}, 2);
    t_is(got.xcols, mpce.xcols, 12, t);

    t = 'mpc = e2i_field(mpc, {''field1'', ''field2''}, ordering)';
    ex = mpce.x.more(gen_i2e, :);
    got = e2i_field(mpc, {'x', 'more'}, 'gen');
    t_is(got.x.more, ex, 12, t);
    t = 'mpc = i2e_field(mpc, {''field1'', ''field2''}, ordering)';
    got = i2e_field(got, {'x', 'more'}, 'gen');
    t_is(got.x.more, mpce.x.more, 12, t);

    t = 'mpc = e2i_field(mpc, {''field1'', ''field2''}, ordering, 2)';
    ex = mpce.x.more(:, gen_i2e);
    got = e2i_field(mpc, {'x', 'more'}, 'gen', 2);
    t_is(got.x.more, ex, 12, t);
    t = 'mpc = i2e_field(mpc, {''field1'', ''field2''}, ordering, 2)';
    got = i2e_field(got, {'x', 'more'}, 'gen', 2);
    t_is(got.x.more, mpce.x.more, 12, t);

    %%-----  mpc = e2i_field/i2e_field(mpc, cellfield, ...)  -----
    t = 'mpc = e2i_field(mpc, cellfield, ''bus'')';
    mpc = ext2int(mpce);
    ex = mpce.strbus;
    ex(6, :) = [];
    got = e2i_field(mpc, 'strbus', 'bus');
    t_is(cellfun(@str2num, got.strbus), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''bus'')';
    got = i2e_field(got, 'strbus', 'bus');
    t_is(cellfun(@str2num, got.strbus), cellfun(@str2num, mpce.strbus), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, ''bus'', 2)';
    ex = mpce.strbus;
    ex(:, 6) = [];
    got = e2i_field(mpc, 'strbus', 'bus', 2);
    t_is(cellfun(@str2num, got.strbus), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''bus'', 2)';
    got = i2e_field(got, 'strbus', 'bus', 2);
    t_is(cellfun(@str2num, got.strbus), cellfun(@str2num, mpce.strbus), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, ''gen'')';
    ex = mpce.strgen(gen_i2e, :);
    got = e2i_field(mpc, 'strgen', 'gen');
    t_is(cellfun(@str2num, got.strgen), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''gen'')';
    got = i2e_field(got, 'strgen', 'gen');
    t_is(cellfun(@str2num, got.strgen), cellfun(@str2num, mpce.strgen), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, ''gen'', 2)';
    ex = mpce.strgen(:, gen_i2e);
    got = e2i_field(mpc, 'strgen', 'gen', 2);
    t_is(cellfun(@str2num, got.strgen), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''gen'', 2)';
    got = i2e_field(got, 'strgen', 'gen', 2);
    t_is(cellfun(@str2num, got.strgen), cellfun(@str2num, mpce.strgen), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, ''branch'')';
    ex = mpce.strbranch;
    ex(7, :) = [];
    got = e2i_field(mpc, 'strbranch', 'branch');
    t_is(cellfun(@str2num, got.strbranch), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''branch'')';
    got = i2e_field(got, 'strbranch', 'branch');
    t_is(cellfun(@str2num, got.strbranch), cellfun(@str2num, mpce.strbranch), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, ''branch'', 2)';
    ex = mpce.strbranch;
    ex(:, 7) = [];
    got = e2i_field(mpc, 'strbranch', 'branch', 2);
    t_is(cellfun(@str2num, got.strbranch), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, ''branch'', 2)';
    got = i2e_field(got, 'strbranch', 'branch', 2);
    t_is(cellfun(@str2num, got.strbranch), cellfun(@str2num, mpce.strbranch), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, {''branch'', ''gen'', ''bus''})';
    ex = [mpce.strbranch([1:6, 8:10], 1:4); mpce.strgen(gen_i2e, :); mpce.strbus([1:5, 7:10], 1:4); cellfun(@num2str, num2cell(-ones(2, 4)), 'UniformOutput', 0)];
    got = e2i_field(mpc, 'strrows', {'branch', 'gen', 'bus'});
    t_is(cellfun(@str2num, got.strrows), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, {''branch'', ''gen'', ''bus''})';
    got = i2e_field(got, 'strrows', {'branch', 'gen', 'bus'});
    t_is(cellfun(@str2num, got.strrows), cellfun(@str2num, mpce.strrows), 12, t);

    t = 'mpc = e2i_field(mpc, cellfield, {''branch'', ''gen'', ''bus''}, 2)';
    ex = [mpce.strbranch([1:6, 8:10], 1:4); mpce.strgen(gen_i2e, :); mpce.strbus([1:5, 7:10], 1:4); cellfun(@num2str, num2cell(-ones(2, 4)), 'UniformOutput', 0)]';
    got = e2i_field(mpc, 'strcols', {'branch', 'gen', 'bus'}, 2);
    t_is(cellfun(@str2num, got.strcols), cellfun(@str2num, ex), 12, t);
    t = 'mpc = i2e_field(mpc, cellfield, {''branch'', ''gen'', ''bus''})';
    got = i2e_field(got, 'strcols', {'branch', 'gen', 'bus'}, 2);
    t_is(cellfun(@str2num, got.strcols), cellfun(@str2num, mpce.strcols), 12, t);

    %%-----  more mpc = ext2int/int2ext(mpc)  -----
    t = 'mpc = ext2int(mpc) - bus/gen/branch only : ';
    mpce = loadcase('t_case_ext');
    mpci = loadcase('t_case_int');
    mpce = rmfield(mpce, 'gencost');
    mpce = rmfield(mpce, 'A');
    mpce = rmfield(mpce, 'N');
    mpci = rmfield(mpci, 'gencost');
    mpci = rmfield(mpci, 'A');
    mpci = rmfield(mpci, 'N');
    mpc = ext2int(mpce);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);

    t = 'mpc = ext2int(mpc) - Qg cost, no N : ';
    mpce = loadcase('t_case_ext');
    mpci = loadcase('t_case_int');
    mpce = rmfield(mpce, 'N');
    mpci = rmfield(mpci, 'N');
    mpce.gencost = [mpce.gencost; mpce.gencost];
    mpci.gencost = [mpci.gencost; mpci.gencost];
    mpc = ext2int(mpce);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);

    t = 'mpc = ext2int(mpc) - A, N are DC sized : ';
    mpce = loadcase('t_case_ext');
    mpci = loadcase('t_case_int');
    eVmQgcols = [11:20 25:28]';
    iVmQgcols = [10:18 22:24]';
    mpce.A(:, eVmQgcols) = [];
    mpce.N(:, eVmQgcols) = [];
    mpci.A(:, iVmQgcols) = [];
    mpci.N(:, iVmQgcols) = [];
    mpc = ext2int(mpce);
    t_is(mpc.bus, mpci.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpci.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpci.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpci.gencost, 12, [t 'gencost']);
    t_is(mpc.A, mpci.A, 12, [t 'A']);
    t_is(mpc.N, mpci.N, 12, [t 'N']);

    t = 'mpc = int2ext(mpc) - A, N are DC sized : ';
    mpc = int2ext(mpc);
    t_is(mpc.bus, mpce.bus, 12, [t 'bus']);
    t_is(mpc.branch, mpce.branch, 12, [t 'branch']);
    t_is(mpc.gen, mpce.gen, 12, [t 'gen']);
    t_is(mpc.gencost, mpce.gencost, 12, [t 'gencost']);
    t_is(mpc.A, mpce.A, 12, [t 'A']);
    t_is(mpc.N, mpce.N, 12, [t 'N']);

    t = 'mpc = ext2int(mpc) - all buses isolated : ';
    mpc = loadcase('t_case_ext');
    mpc.bus(:, BUS_TYPE) = NONE;
    try
        mpci = ext2int(mpc);
        t_is(size(mpci.bus, 1), 0, 12, [t 'internal case empty']);
    catch
        t_ok(0, [t 'unexpected fatal error']);
    end

    t = 'mpc = int2ext(mpc) - all buses isolated : ';
    try
        mpce = int2ext(mpci);
        t_is(mpc.bus, mpce.bus, 12, [t 'bus']);
        t_is(mpc.branch, mpce.branch, 12, [t 'branch']);
        t_is(mpc.gen, mpce.gen, 12, [t 'gen']);
        t_is(mpc.gencost, mpce.gencost, 12, [t 'gencost']);
        t_is(mpc.A, mpce.A, 12, [t 'A']);
        t_is(mpc.N, mpce.N, 12, [t 'N']);
    catch
        t_ok(0, [t 'unexpected fatal error']);
        t_skip(5, [t 'unexpected fatal error']);
    end
end

t_end;

function mpc = userfcn_test_ext2int(mpc, mpopt, args)

function results = userfcn_test_int2ext(results, mpopt, args)


% STD_READLIMOFILE- Read limo file into eeglab structure
%
% Usage:
%   >> [MeasureData, parameters, MeasureRange1, MeasureRange2] = std_readfilelimo(filestruct,'key', val)
%
% Inputs:
% filestrcuct  - Structure with the following fields:
%                datasets : Index of he datasets in datasetinfo (real)
%                trials   : index of the trials to pull out     (cell array)
%                value    : Cell array with the values of the independent variables of the set.
%                case     : name of the subject /case
%                filebase : Full Path and filename of the
%
% Optional inputs:
%   'measure'     - ['itcbeta1' | 'itcbeta2' |'itcr2r' |'itcr2f' |'itcr2p' |
%                    'erpbeta1' | 'erpbeta2' |'erpr2r' |'erpr2f' |'erpr2p' |
%                    'erspbeta1'| 'erspbeta2'|'erspr2r'|'erspr2f'|'erspr2p'|
%                    'specbeta1'| 'specbeta2'|'specr2r'|'specr2f'|'specr2p ]
%   'timelimits'  - [min max] ERSP time (latency in ms) range of interest
%   'freqlimits'  - [min max] ERSP frequency range (in Hz) of interest
%   'channels'    - [cell or integer] channel labels - for instance
%                   { 'cz' 'pz' }
%
% Outputs:
%   MeasureData    - the multi-channel or multi-component data. The size of this
%                    output depends on the number of dimension (for ERSP or ERP
%                    for instance). The last dimension is channels or components.
%   parameters     - structure containing parameters saved with the data file.
%   MeasureRange1  - time points (ERP, ERSP) or frequency points (spectrum)
%   MeasureRange2  - frequency points (ERSP, ITCs)
%
%
%
% See also:
%
%
% Authors: Arnaud Delorme, Ramon Martinez-Cancino
%
% Copyright (C) 2014  Ramon Martinez-Cancino,INC, SCCN
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
function [MeasureData, parameters, MeasureRange1, MeasureRange2] = std_readfilelimo(filestruct, varargin)

parameters = [];
try
    options = varargin;
    if ~isempty( varargin ),
        for i = 1:2:numel(options)
            g.(options{i}) = options{i+1};
        end
    else g = []; end
catch
    error('std_readfilelimo() error: calling convention {''key'', value, ... } error');
end

try, g.channels;                catch, g.channels          = [];        end; %
try, g.components;              catch, g.components        = [];        end; %
try, g.measure;                 catch, g.measure           = [];        end; %
try, g.timelimits;              catch, g.timelimits        = [];        end; %
try, g.triallimits;             catch, g.triallimits       = [];        end; %
try, g.freqlimits;              catch, g.freqlimits        = [];        end; %
try, g.getparamonly;            catch, g.getparamonly      = 'off';     end; %  work on this

%  Checking entries
%..........................................................................

% Indetify if components or channels
%..........................................................................
if isempty(g.components)
    chanoric = 'Channels';
else
    chanoric = 'Components';
end

% Identify type of analysis for limo stuff path
%..........................................................................
if strcmp(g.measure(1:3),'erp') && strcmp(chanoric,'Channels')
    type = 'Channels_Time';
elseif strcmp(g.measure(1:3),'erp') && strcmp(chanoric,'Components')
    type = 'Components_Time';
elseif strcmp(g.measure(1:3),'spe') && strcmp(chanoric,'Channels')
    type = 'Channels_Frequency';
elseif strcmp(g.measure(1:3),'spe') && strcmp(chanoric,'Components')
    type = 'Components_Frequency';
elseif strcmp(g.measure(1:3),'ers') && strcmp(chanoric,'Channels')
    type = 'Channels_Time-Frequency';
elseif strcmp(g.measure(1:3),'ers') && strcmp(chanoric,'Components')
    type = 'Components_Time-Frequency';
end

% Study pathname
%..........................................................................
filebasetemp = filestruct.filebase;
[path, name, tmp] = fileparts(filebasetemp);
[path2study,tmp,tmp]= fileparts(path);

% Getting design index in STUDY
%..........................................................................
designindx = name(7:9);
if isempty(str2num(designindx))
    designindx = designindx(1:2);
    if isempty(str2num(designindx))
        designindx = designindx(1);
        if isempty(str2num(designindx))
            error('std_readfilelimo(): Fail to detect index of the design in STUDY');
        end
    end
end

% Creating path to LIMO.mat and loading it
%..........................................................................
filelist        = dir(path2study);
fileindxtmp     = strmatch('LIMO_', {filelist.name});
limofoldername  = filelist(fileindxtmp(1)).name;
path2limofiles  = [path2study filesep limofoldername filesep filestruct.case filesep 'GLM' num2str(designindx) '_' type];
structmp        = load ([path2limofiles filesep 'LIMO.mat']);
limostruct      = structmp.LIMO;

% Identifying condition
%..........................................................................
dims = []; cond_indxs = [];
condtemp = {limostruct.data.studyinfo.value};

for i =  1 : length(condtemp)
    dims(i)       = length(condtemp{i});
    tmp = condtemp{i};
    for j = 1: dims(i)
        tmp{j} = num2str(tmp{j});
    end
    condtemp{i} = tmp;
    cond_indxs(i) = find(strcmp(condtemp{i},num2str(filestruct.value{i})));
end
% Sub2ind stuff
command = 'sub2ind(dims';
for i = 1: length(dims)
    command = [command ',cond_indxs(' num2str(i) ')'];
end
command = [command ')'];
CondIndx = eval(command);

% Checking time and set TimeIndxVec if type = TIME
%..........................................................................
if all([~isempty(g.timelimits),isfield(limostruct.data,'sampling_rate')])
    if any([g.timelimits(1) < limostruct.data.start, g.timelimits(2) > limostruct.data.end])
        error('std_readfilelimo(): Time indices provided are out of bonds');
    else
        TimeVec = limostruct.data.start: 1000/limostruct.data.sampling_rate:limostruct.data.end
        [tmp,TimeIndx(1)] = min(abs(TimeVec - g.timelimits(1)));
        [tmp,TimeIndx(2)] = min(abs(TimeVec - g.timelimits(2)));
        TimeIndxVec = TimeIndx(1):TimeIndx(2);
    end
elseif all([isempty(g.timelimits),isfield(limostruct.data,'sampling_rate')]) % will use all the timepoints
    TimeIndxVec = 1:length(limostruct.data.start: 1000/limostruct.data.sampling_rate:limostruct.data.end);
end

% Checking frequencies and set FreqIndxVec if type = Frequency
%..........................................................................
 if all([~isempty(g.freqlimits),isfield(limostruct.data,'freqlist')])
     if any([g.freqlimits(1) < limostruct.data.lowf, g.freqlimits(2) > limostruct.data.highf])
         error('std_readfilelimo(): Frequency indices provided are out of bonds');
     else
         [tmp,FreqIndx(1)] = min(abs(limostruct.data.freqlist - g.freqlimits(1)));
         [tmp,FreqIndx(2)] = min(abs(limostruct.data.freqlist - g.freqlimits(2)));
         FreqIndxVec = FreqIndx(1):FreqIndx(2);
     end
 elseif all([isempty(g.freqlimits),isfield(limostruct.data,'freqlist')]) % will use all frequencies
     FreqIndxVec = 1 : length(limostruct.data.freqlist);
 end

 % Checking frequencies and time and set FreqIndxVec and TimeIndxVec if type = Time-Frequency
 %..........................................................................
 if all([isfield(limostruct.data,'tf_times'), isfield(limostruct.data,'tf_freq')])

     %1- Time
     if ~isempty(g.timelimits)
         if any([g.timelimits(1) < limostruct.data.start, g.timelimits(2) > limostruct.data.end])
             error('std_readfilelimo(): Time indices provided are out of bonds');
         else
             [tmp,TimeIndx(1)] = min(abs(limostruct.data.tf_times - g.timelimits(1)));
             [tmp,TimeIndx(2)] = min(abs(limostruct.data.tf_times - g.timelimits(2)));
             TimeIndxVec = TimeIndx(1):TimeIndx(2);
         end
     else % will use all timepoints
         TimeIndxVec = 1:length(limostruct.data.tf_times);
     end

     %2- Frequency
     if ~isempty(g.freqlimits)
         if any([g.freqlimits(1) < limostruct.data.lowf, g.freqlimits(2) > limostruct.data.highf])
             error('std_readfilelimo(): Frequency indices provided are out of bonds');
         else
             [tmp,FreqIndx(1)] = min(abs(limostruct.data.tf_freqs - g.freqlimits(1)));
             [tmp,FreqIndx(2)] = min(abs(limostruct.data.tf_freqs - g.freqlimits(2)));
             FreqIndxVec = FreqIndx(1):FreqIndx(2);
         end
     else % will use all frequencies
         FreqIndxVec = 1:length(limostruct.data.tf_freqs);
     end

 end

% Checking channels or ic to load
%..........................................................................
% 1- Channels
if isempty(g.channels) && strcmp(chanoric, 'Channels')
    ChanIcIndx = 1:length({limostruct.data.chanlocs.labels});
elseif ~isempty(g.channels) && strcmp(chanoric, 'Channels')
     for i = 1 : length(g.channels)
         if isempty(find(strcmp(lower(g.channels(i)),lower({limostruct.data.chanlocs.labels}))))
             error('std_readfilelimo(): Invalid channel label');
         else
             ChanIcIndx = find(strcmp(lower(g.channels(i)),lower({limostruct.data.chanlocs.labels})));
         end
     end
end

% 2- Component
if isempty(g.components) && strcmp(chanoric, 'Components')
    ChanIcIndx = 1:length({limostruct.data.chanlocs.labels});
elseif ~isempty(g.channels) && strcmp(chanoric, 'Components')
     for i = 1 : length(g.channels)
         if isempty(find(strcmp(g.channels(i),{limostruct.data.chanlocs.labels})))
             error('std_readfilelimo(): Invalid channel label');
         else
             ChanIcIndx = find(strcmp(g.channels(i),{limostruct.data.chanlocs.labels}));
         end
     end
end

% Retrieving data
%..........................................................................
if isfield(limostruct.data,'sampling_rate')
    TimeVec = limostruct.data.start: 1000/limostruct.data.sampling_rate:limostruct.data.end
end

switch g.measure
    % beta1
    %..................................................................
    case 'erpbeta1'
        datatmp = load([path2limofiles filesep 'Betas.mat']); % PUT THIS OUT OF THE LOOP
        data = datatmp.Betas;
        MeasureData   = data(ChanIcIndx,TimeIndxVec,CondIndx);   % Chan/IC x Time x Condition

    case 'specbeta1'
        datatmp = load([path2limofiles filesep 'Betas.mat']);
        data = datatmp.Betas;
        MeasureData   = data(ChanIcIndx,FreqIndxVec,CondIndx);   % Chan/IC x Freq x Condition

    case {'erspbeta1','itcbeta1'}
        datatmp = load([path2limofiles filesep 'Betas.mat']);
        data = datatmp.Betas;
        MeasureData   = data(FreqIndxVec, TimeIndxVec,CondIndx); % Freq x Time x Condition

    % beta2
    %..................................................................
    case {'erpbeta2','erspbeta2','specbeta2','itcbeta2'}
        error('std_readfilelimo(): Invalid option in this realease');

    % erpr2
    %..................................................................
    case 'erpr2r'
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,TimeIndxVec,1);

     case 'erpr2f'
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,TimeIndxVec,2);

    case 'erpr2p'
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,TimeIndxVec,3);

    % erspr2 & itcr2
    %..................................................................
    case {'erspr2r','itcr2r'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(FreqIndxVec,TimeIndxVec,1);

     case {'erspr2f','itcr2f'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(FreqIndxVec,TimeIndxVec,2);

    case {'erspr2p','itcr2p'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(FreqIndxVec,TimeIndxVec,3);

    %spec
    %..................................................................
    case {'specr2r'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,FreqIndxVec,1);

     case {'specr2f'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,FreqIndxVec,2);

    case {'specr2p'}
        datatmp = load([path2limofiles filesep 'R2.mat']);
        data = datatmp.R2;
        MeasureData   = data(ChanIcIndx,FreqIndxVec,3);
end

% Measures ranges
%..........................................................................
switch g.measure(1:3)
    case 'erp'
        MeasureRange1 = TimeVec(TimeIndxVec);
        MeasureRange2 = [];
    case {'ers','itc'}
        MeasureRange1 = limostruct.data.tf_times(TimeIndxVec);
        MeasureRange2 = limostruct.data.tf_freqs(FreqIndxVec);
    case 'spe'
        MeasureRange1 = limostruct.data.freqlist(FreqIndxVec);
        MeasureRange2 = [];
end


function mtrThresholdResampleSISPathways(fgFilenames,samplerOptsFilename,weightThreshold,dt6Filename,fgResampledFilename,bCalcStats)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% mtrThresholdResampleSISPathways(fgFilenames,samplerOptsFilename,
%%                                numSamplesPerCluster,clusterROI,
%%                                fgResampledFilename)
%%
%% fgFilenames - filenames for metrotrac pathways
%% samplerOptsFilename - parameters file for collecting paths and stats
%% fgResampledFilename - filename for resampled pathways
%% dt6Filename - Filename for dt6.
%% hintNumTotalFibers - Number hopefully greater than the total number of
%% fibers that we will load.  This will speed up processing significantly
%% as it will allow us to preallocate space for validity matrix.
%% bCalcStats - True then calculate the statistics False then they already
%% exist.
%%
%%
%% Author: Anthony Sherbondy
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% MUST MAKE SURE THIS PROGRAM IS COMPILED AND IN RIGHT LOCATION
if(ispc)
    executable = which('updatestats.exe');
else
    error('Not compiled for Linux.');
end

% Get all the needed files
if(ieNotDefined('dt6Filename'))
    [f, p] = uigetfile({'*.mat';'*.*'}, 'Load DT6 file...');
    if(isnumeric(f)), disp('Resampling canceled.'); return; end
    dt6Filename = fullfile(p,f);
end

dt6 = load(dt6Filename);

% Get importance weight file that we need to resample with also load the
% pathfile into matlab
totalFiberCount = 1;
fg_input = dtiNewFiberGroup;
fg_temp = dtiNewFiberGroup;

for ii = 1:length(fgFilenames)
     tic;
    statvec_names{ii} = sprintf('temp%d_statvec_iw.dat',ii);
    if(bCalcStats)
        disp('Calculating Statistics.');
        args = sprintf(' -v %s -i %s -o temp.dat -s 4 -sf %s', samplerOptsFilename, fgFilenames{ii}, statvec_names{ii});
        cmd = [executable args];
        disp(cmd); disp('...')
        [s, ret_info] = system(cmd,'-echo');
        disp('Done.')
    end

    disp('Loading pathway file into matlab...')
    fg_temp = mtrImportFibers(fgFilenames{ii}, dt6.xformToAcPc);
    disp('Done')

    % Keep aggregating all of the fibers together into one group
    if(isempty(fg_input.fibers))
        fg_input.fibers = fg_temp.fibers;
    else
        fg_input.fibers = [fg_input.fibers(:), fg_temp.fibers(:)];
    end
     toc;
end
clear fg_temp;

% Send the valid matrix in with the resample computations
[fg_output, sample_w] = resampleThresholdSISPathways(weightThreshold, statvec_names, fg_input);

% Output the pathways in dtifiberUI space
%dtiWriteFiberGroup(fg_output,fgResampledFilename);

% Output the pathways in metrotrac space
mtrExportFiberGroupToMetrotrac(fgResampledFilename,fg_output,dt6.t1NormParams,dt6.mmPerVox,dt6.xformToAcPc,size(dt6.b0));

% Cleanup temp files
delete('temp.dat');

% Why should I delete these stats?? they are yummy!!
% for ii = 1:length(statvec_names)
%     delete(statvec_names{ii});
% end

return;

function [fg_output, sample_w_out] = resampleThresholdSISPathways(weightThreshold, weightFilenames, fg_input)

numFiles = length(weightFilenames);
sizeFiles = [];

% Setup the output file
fg_output = dtiNewFiberGroup;

% Load multiple importance weight files
iw = [];
for f = 1:numFiles
    iwtemp = mtrLoadStatvec(weightFilenames{f});
    iw = [iw; iwtemp];
    sizeFiles(f) = length(iwtemp);
end
% Now just threshold the paths based on weightThreshold
iwThresholded = find(iw > weightThreshold);

% Get the paths that survive the threshold
fg_output.fibers = fg_input.fibers(iwThresholded);
sample_w_out = ones(size(fg_output.fibers));

return;


%% Settings

robotName='iCubGenova04'; %% Name of the robot

testFrames = {'l_hand', 'r_hand', 'head'}; %% The frames to display

meshFilePrefix = [getenv('ROBOTOLOGY_SUPERBUILD_INSTALL_PREFIX') '/share']; %% Path to the model meshes

modelPath = [getenv('ROBOTOLOGY_SUPERBUILD_INSTALL_PREFIX') '/share/iCub/robots/' robotName '/'];  %% Path to the robot model

fileName='model.urdf'; %% Name of the urdf file

jointOrder={     %% The list and the order of the joints
    'r_hip_pitch';
    'r_hip_roll';
    'r_hip_yaw';
    'r_knee';
    'r_ankle_pitch';
    'r_ankle_roll';
    'l_hip_pitch';
    'l_hip_roll';
    'l_hip_yaw';
    'l_knee';
    'l_ankle_pitch';
    'l_ankle_roll';
    'torso_pitch';
    'torso_roll';
    'torso_yaw';
    'r_shoulder_pitch';
    'r_shoulder_roll';
    'r_shoulder_yaw';
    'r_elbow';
    'r_wrist_prosup';
    'r_wrist_pitch';
    'r_wrist_yaw';
    'l_shoulder_pitch';
    'l_shoulder_roll';
    'l_shoulder_yaw';
    'l_elbow';
    'l_wrist_prosup';
    'l_wrist_pitch';
    'l_wrist_yaw';
    'neck_pitch';
    'neck_roll';
    'neck_yaw'
    };

groundFrame = 'l_sole'; %% The frame where to place the ground

rootLink = 'root_link'; %% The base link

joints_positions=zeros(length(jointOrder),1); %% The joints'position

printModel = true; %% Define if the model has to be printed on the command window

%% No need to edit from here

% Main variable of iDyntreeWrappers used for many things including updating
% robot position and getting world to frame transforms
KinDynModel = iDynTreeWrappers.loadReducedModel(jointOrder, rootLink, modelPath,fileName,false);

if printModel
    KinDynModel.kinDynComp.model().toString() %%Print model
end

% Set initial position of the robot
iDynTreeWrappers.setRobotState(KinDynModel,eye(4),joints_positions,zeros(6,1),zeros(size(joints_positions)),[0,0,-9.81]);

groundFrameTransform = iDynTreeWrappers.getWorldTransform(KinDynModel, groundFrame);

world_H_base = groundFrameTransform^-1;

iDynTreeWrappers.setRobotState(KinDynModel,world_H_base,joints_positions,zeros(6,1),zeros(size(joints_positions)),[0,0,-9.81]);

% Prepare figure, handles and variables required for the update, some extra
% options are commented.
[visualizer,objects]=iDynTreeWrappers.prepareVisualization(KinDynModel,meshFilePrefix,...
    'color',[1,1,1],'transparency',1, 'name', ['Plot frame ', robotName], 'reuseFigure', 'name');
xlim([-0.5, 0.5])
ylim([-0.5, 0.5])
zlim([-0.05, 1.4])

for t = 1 : length(testFrames)
    frameTransform = iDynTreeWrappers.getWorldTransform(KinDynModel, testFrames{t});
    testFramesObjects{t} = iDynTreeWrappers.plotFrame(frameTransform, 0.2, 5);
end


classdef SteeringModelEnum < matlab.mixin.SetGet
    %SteeringModelEnum Summary of this class goes here
    %   Detailed explanation goes here

    enumeration
        RollPitchYawPoly('Roll/Pitch/Yaw Steering','RollPitchYawPolySteeringModel', true);
        AeroAnglesPoly('Body Fixed Aero Angles Steering','AeroAnglesPolySteeringModel', true);
        InertialAeroAnglesPoly('Inertial Aero Angles Steering','InertialAeroAnglesPolySteeringModel', true);
        GenericPoly('Generic Angles Steering','GenericPolySteeringModel', true);

        GenericQuatInterp('Generic Angles Quaternion Interp','GenericQuatInterpSteeringModel', false);
        GenericSelectable('Generic Selectable Model Steering','GenericSelectableSteeringModel', false);
    end

    enumeration(Hidden)
        GenericLinTan('Generic Linear Tangent Angles Steering','GenericLinearTangentSteeringModel', false);
        GenericSumOfSines('Generic Sum of Sines Angles Steering','GenericSumOfSinesSteeringModel', false);
    end

    properties
        nameStr char = '';
        classNameStr char = '';
        showInPolyUi(1,1) logical = false;
    end

    methods
        function obj = SteeringModelEnum(nameStr,classNameStr,showInPolyUi)
            obj.nameStr = nameStr;
            obj.classNameStr = classNameStr;
            obj.showInPolyUi = showInPolyUi;
        end
    end

    methods(Static)
        function steeringModelNameStrs = getSteeringModelTypeNameStrs(showInPylUiMustBe)
            [m,~] = enumeration('SteeringModelEnum');
            m = m([m.showInPolyUi] == showInPylUiMustBe);

            steeringModelNameStrs = {};
            for(i=1:length(m)) %#ok<*NO4LP>
                steeringModelNameStrs{end+1} = m(i).nameStr; %#ok<AGROW>
            end
        end

        function ind = getIndOfListboxStrsForSteeringModel(steeringModel)
            [m,~] = enumeration('SteeringModelEnum');
            inputClass = class(steeringModel);

            ind = -1;
            for(i=1:length(m))
                if(strcmpi(m(i).classNameStr,inputClass))
                    ind = i;
                    break;
                end
            end
        end
    end
end