function varargout = CoilDesignPanel(varargin)
% CoilDESIGNPANEL M-file for CoilDesignPanel.fig
%      CoilDESIGNPANEL, by itself, creates a new CoilDESIGNPANEL or raises the existing
%      singleton*.
%
%      H = CoilDESIGNPANEL returns the handle to a new CoilDESIGNPANEL or the handle to
%      the existing singleton*.
%
%      CoilDESIGNPANEL('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in CoilDESIGNPANEL.M with the given input arguments.
%
%      CoilDESIGNPANEL('Property','Value',...) creates a new CoilDESIGNPANEL or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before CoilDesignPanel_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to CoilDesignPanel_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help CoilDesignPanel

% Last Modified by GUIDE v2.5 17-Apr-2014 19:26:20

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @CoilDesignPanel_OpeningFcn, ...
    'gui_OutputFcn',  @CoilDesignPanel_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before CoilDesignPanel is made visible.
function CoilDesignPanel_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to CoilDesignPanel (see VARARGIN)
global VCtl;
global VObj;
global VMco;

handles.Simuh=varargin{1};
% Load coil element list
try
    handles.CoilElemListStruct=DoParseXML([handles.Simuh.MRiLabPath filesep 'Macro' filesep 'CoilElem' filesep 'CoilElem.xml']);
    guidata(hObject,handles);
    Root=DoConvStruct2Tree(handles.CoilElemListStruct);
    handles.CoilElemListTree=uitree('v0', 'Root',Root,'SelectionChangeFcn', {@ChkCoilElemListTreeNode,handles});
    set(handles.CoilElemListTree.getUIContainer,'Units','normalized');
    set(handles.CoilElemListTree.getUIContainer,'Position',[0.0,0.4,0.2,0.58]);
    handles.Attrh1=[];
catch ME
    errordlg('Coil element list can not be loaded!');
    close(hObject);
    return;
end

%Load tabs for coil simulation
try
    handles.CoilSimuAttrStruct=DoParseXML([handles.Simuh.MRiLabPath filesep 'Macro' filesep 'CoilElem' filesep 'CoilSimuAttr.xml']);
catch ME
    errordlg('CoilSimuAttr.xml file is missing or can not be loaded!');
    close(hObject);
    return;
end

handles.Setting_tabgroup=uitabgroup(handles.Setting_uipanel);
guidata(handles.CoilDesignPanel_figure,handles);
for i=1:length(handles.CoilSimuAttrStruct.Children)
    eval(['handles.' handles.CoilSimuAttrStruct.Children(i).Name '_tab=uitab( handles.Setting_tabgroup,' '''title'',' '''' handles.CoilSimuAttrStruct.Children(i).Name ''',''Units'',''normalized'');']);
    eval(['DoEditValue(handles,handles.' handles.CoilSimuAttrStruct.Children(i).Name '_tab,handles.CoilSimuAttrStruct.Children(' num2str(i) ').Attributes,2,[0.2,0.15,0.0,0.15,0.15,0.05]);']);
    handles=guidata(handles.CoilDesignPanel_figure);
end

% Create grid and display structure
VMco.xdimres=str2num(get(handles.Attrh2.('XDimRes'),'String'));
VMco.ydimres=str2num(get(handles.Attrh2.('YDimRes'),'String'));
VMco.zdimres=str2num(get(handles.Attrh2.('ZDimRes'),'String'));

Mxdims=size(VObj.Rho);
[VMco.xgrid,VMco.ygrid,VMco.zgrid]=meshgrid((-(Mxdims(2)-1)/2)*VObj.XDimRes:VMco.xdimres:((Mxdims(2)-1)/2)*VObj.XDimRes,...
    (-(Mxdims(1)-1)/2)*VObj.YDimRes:VMco.ydimres:((Mxdims(1)-1)/2)*VObj.YDimRes,...
    (-(Mxdims(3)-1)/2)*VObj.ZDimRes:VMco.zdimres:((Mxdims(3)-1)/2)*VObj.ZDimRes);
VMco.axes=handles.CoilSen_axes;
handles.IV=struct(...
    'xslice',(handles.Simuh.SV.Slice - (Mxdims(2)-1)/2)* VObj.XDimRes,...
    'yslice',(handles.Simuh.CV.Slice - (Mxdims(1)-1)/2)* VObj.YDimRes,...
    'zslice',(handles.Simuh.AV.Slice - (Mxdims(3)-1)/2)* VObj.ZDimRes ...
    );
view(handles.CoilSen_axes,3);

if verLessThan('matlab','8.5')
    % Code to run in MATLAB R2015a and earlier here
    %Open current loaded Coil XML file
    if strcmp(get(handles.Simuh.CoilTx_tab,'Visible'),'on')
        if isfield(handles.Simuh,'CoilTxXMLFile')
            CoilXMLFile = handles.Simuh.CoilTxXMLFile;
        end
    end

    if strcmp(get(handles.Simuh.CoilRx_tab,'Visible'),'on')
        if isfield(handles.Simuh,'CoilRxXMLFile')
            CoilXMLFile = handles.Simuh.CoilRxXMLFile;
        end
    end
else
    % Code to run in MATLAB R2015a and later here
    tabtitle=get(get(handles.Simuh.CoilSel_tabgroup,'SelectedTab'),'Title');
    if strcmp(tabtitle,'Tx')
        if isfield(handles.Simuh,'CoilTxXMLFile')
            CoilXMLFile = handles.Simuh.CoilTxXMLFile;
        end
    elseif strcmp(tabtitle,'Rx')
        if isfield(handles.Simuh,'CoilRxXMLFile')
            CoilXMLFile = handles.Simuh.CoilRxXMLFile;
        end
    end
end

if exist('CoilXMLFile','var')
    import javax.swing.*
    import javax.swing.tree.*;
    handles.CoilStruct=DoParseXML(CoilXMLFile);
    handles.CoilXMLFile=CoilXMLFile;
    DoWriteXML2m(handles.CoilStruct,[handles.CoilXMLFile(1:end-3) 'm']);
    %     guidata(hObject, handles);
    Root=DoConvStruct2Tree(handles.CoilStruct);
    handles.CoilTree=uitree('V0','Root',Root,'SelectionChangeFcn', {@ChkNode,handles});
    set(handles.CoilTree.getUIContainer,'Units','normalized');
    set(handles.CoilTree.getUIContainer,'Position',[0.205,0.4,0.2,0.58]);
    handles.CoilTreeModel=DefaultTreeModel(Root);
    handles.CoilTree.setModel(handles.CoilTreeModel);
    try
        DoPlotCoilSen(handles);
        set(handles.Undock_pushbutton,'Enable','on');
        set(handles.Display_pushbutton,'Enable','on');
        set(handles.Forwards_pushbutton,'Enable','on');
        set(handles.Backwards_pushbutton,'Enable','on');
        handles=guidata(hObject);
    catch me
        error_msg{1,1}='ERROR!!! Displaying B1 field aborted.';
        error_msg{2,1}=me.message;
        errordlg(error_msg);
    end

end

% Choose default command line output for CoilDesignPanel
handles.input=varargin;
handles.output=hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes CoilDesignPanel wait for user response (see UIRESUME)
% uiwait(handles.CoilDesignPanel_figure);

function ChkCoilElemListTreeNode(tree, value, handles)

handles=guidata(handles.CoilDesignPanel_figure);
SelNode=tree.SelectedNodes;
SelNode=SelNode(1);
Level=SelNode.getValue;
if ~ischar(Level)
    LevelChg=diff(Level,1);
    Level([LevelChg; -1]==1)=[];
end

Node='handles.CoilElemListStruct';
if Level=='0'
    eval(['handles.CoilElemNode=' Node ';']);
else
    for i=1:length(Level)
        Node=[Node '.Children(' num2str(Level(i)) ')'];
    end
    eval(['handles.CoilElemNode=' Node ';']);
end
guidata(handles.CoilDesignPanel_figure, handles);

% --- Outputs from this function are returned to the command line.
function varargout = CoilDesignPanel_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = hObject;

% --------------------------------------------------------------------
function LoadCoil_uimenu_Callback(hObject, eventdata, handles)
% hObject    handle to LoadCoil_uimenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function LoadCoilFile_uimenu_Callback(hObject, eventdata, handles)
% hObject    handle to LoadCoilFile_uimenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

import javax.swing.*
import javax.swing.tree.*;

[filename,coilpathname,filterindex]=uigetfile({'Coil*.xml','XML-files (*.xml)'},'MultiSelect','off');
if filename~=0
    if ~isempty(handles.Attrh1)
        Attrh1name=fieldnames(handles.Attrh1);
        for i=1:length(Attrh1name)
            delete(handles.Attrh1.(Attrh1name{i}));
        end
        handles.Attrh1=[];
    end
    handles.CoilStruct=DoParseXML(fullfile(coilpathname,filename));
    handles.CoilXMLFile=fullfile(coilpathname,filename);
    guidata(hObject, handles);
    Root=DoConvStruct2Tree(handles.CoilStruct);
    handles.CoilTree=uitree('v0', 'Root',Root,'SelectionChangeFcn', {@ChkNode,handles});
    set(handles.CoilTree.getUIContainer,'Units','normalized');
    set(handles.CoilTree.getUIContainer,'Position',[0.205,0.4,0.2,0.58]);
    handles.CoilTreeModel=DefaultTreeModel(Root);
    handles.CoilTree.setModel(handles.CoilTreeModel);
    cla(handles.CoilSen_axes);
    clear global VCco;
    % Add searchig path
    path(path,coilpathname);
else
    errordlg('No Coil is loaded!');
    return;
end
guidata(hObject, handles);

function ChkNode(tree, value, handles)

handles=guidata(handles.CoilDesignPanel_figure);
SelNode=tree.SelectedNodes;
SelNode=SelNode(1);
Level=SelNode.getValue;
if ~ischar(Level)
    LevelChg=diff(Level,1);
    Level([LevelChg; -1]==1)=[];
end
Node='handles.CoilStruct';
if Level=='0'
    eval(['handles.CoilNode=' Node ';']);
else
    for i=1:length(Level)
        Node=[Node '.Children(' num2str(Level(i)) ')'];
    end
    eval(['handles.CoilNode=' Node ';']);
end
handles.CoilNodeLvl=Node;
handles.SelNode=SelNode;

if ~isempty(handles.Attrh1)
    Attrh1name=fieldnames(handles.Attrh1);
    for i=1:length(Attrh1name)
        delete(handles.Attrh1.(Attrh1name{i}));
    end
    handles.Attrh1=[];
end

set(handles.CoilAttri_uipanel,'Title',['''' char(SelNode.getName) ''' Coil Attribute'],'Unit','normalized');
if SelNode.isLeaf | SelNode.isRoot
    if strcmp(char(SelNode.getName),'Specials')
        DoEditValue(handles,handles.CoilAttri_uipanel,handles.CoilNode.Attributes,1,[0.25,0.25,0.0,0.1,0.1,0.05]);
    else
        DoEditValue(handles,handles.CoilAttri_uipanel,handles.CoilNode.Attributes,1,[0.25,0.25,0.0,0.1,0.1,0.05]);
    end
else
    guidata(handles.CoilDesignPanel_figure, handles);
end

% --- Executes on button press in DelNode_pushbutton.
function DelNode_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to DelNode_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

import javax.swing.*
import javax.swing.tree.*;

try
    switch handles.CoilNode.Name
        case 'MRiLabCoil'
            errordlg('MRiLabCoil Root can not be deleted!');
            return;
    end

    eval([handles.CoilNodeLvl '=[];']);
    nN=handles.SelNode.getNextSibling;
    while ~isempty(nN)
        Level=nN.getValue;
        Level(end)=[];
        nN.setValue(Level);
        nN=nN.getNextSibling;
    end
    guidata(hObject, handles);
    pause(0.1);

    % remove node
    handles.CoilTree.setSelectedNode(handles.SelNode.getParent);
    handles.CoilTreeModel.removeNodeFromParent(handles.SelNode);

    DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
catch me
    error_msg{1,1}='ERROR!!! Node operation aborted.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);

end

% --- Executes on button press in AddNode_pushbutton.
function AddNode_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to AddNode_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

import javax.swing.*
import javax.swing.tree.*;

try
    ChkCoilElemListTreeNode(handles.CoilElemListTree, [], handles); % In case CoilElem.xml updated
    handles=guidata(handles.CoilDesignPanel_figure);
    switch handles.CoilNode.Name
        case {'MRiLabCoil'}
            % add node
            SelNode=handles.CoilElemListTree.SelectedNodes;
            SelNode=SelNode(1);
            AddedNode=SelNode.clone;
            switch char(AddedNode.getName)
                case {'CoilElem'}
                    errordlg([char(AddedNode.getName) ' can not be added!']);
                    return;
            end
            handles.CoilTreeModel.insertNodeInto(AddedNode,handles.SelNode,handles.SelNode.getChildCount());
            handles.CoilTree.setSelectedNode(AddedNode); % expand to show added child
            handles.CoilTree.setSelectedNode(handles.SelNode); % insure additional nodes are added to parent

            nP=AddedNode.getPreviousSibling;
            if ~isempty(nP)
                Level=nP.getValue;
                AddedNode.setValue([Level; Level(end)+1]);
                eval([handles.CoilNodeLvl '.Children(' num2str(Level(end)+1) ')=handles.CoilElemNode;']);
                DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
            else
                nP=AddedNode.getParent;
                Level=nP.getValue;
                AddedNode.setValue([Level; 1]);
                eval([handles.CoilNodeLvl '.Children=handles.CoilElemNode;']);
                DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
            end
        otherwise
            errordlg(['Coil Element can not be added under ' handles.CoilNode.Name '!']);
            return;
    end
    guidata(hObject, handles);
catch me
    error_msg{1,1}='ERROR!!! Node operation aborted.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);

end

% --- Executes on button press in UpdateCoilXML_pushbutton.
function UpdateCoilXML_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to UpdateCoilXML_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% update Coil XML file
if ~isempty(handles.Attrh1)
    Attrh1name=fieldnames(handles.Attrh1);
    for i=1:2:length(Attrh1name)
        switch get(handles.Attrh1.(Attrh1name{i+1}),'Style')
            case 'edit'
                handles.CoilNode.Attributes((i+1)/2).Value=get(handles.Attrh1.(Attrh1name{i+1}),'String');
            case 'checkbox'
                if get(handles.Attrh1.(Attrh1name{i+1}),'Value')
                    handles.CoilNode.Attributes((i+1)/2).Value='^1';
                else
                    handles.CoilNode.Attributes((i+1)/2).Value='^0';
                end
            case 'popupmenu'
                handles.CoilNode.Attributes((i+1)/2).Value(2)=num2str(get(handles.Attrh1.(Attrh1name{i+1}),'Value'));
        end
    end
    eval([handles.CoilNodeLvl '=handles.CoilNode;']);
    DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
    % update associated m function
    DoWriteXML2m(handles.CoilStruct,[handles.CoilXMLFile(1:end-3) 'm']);
end

% update CoilSimuAttr.xml
tabs=get(handles.Setting_tabgroup,'Children');
for j=1:length(handles.CoilSimuAttrStruct.Children)
    Attrh2=get(tabs(j),'Children');
    for i=1:2:length(Attrh2)
        if ~iscell(get(Attrh2(end-i),'String'))
            handles.CoilSimuAttrStruct.Children(j).Attributes((i+1)/2).Value=get(Attrh2(end-i),'String');
        else
            handles.CoilSimuAttrStruct.Children(j).Attributes((i+1)/2).Value(2)=num2str(get(Attrh2(end-i),'Value'));
        end
    end
end
DoWriteXML(handles.CoilSimuAttrStruct,[handles.Simuh.MRiLabPath filesep 'Macro' filesep 'CoilElem' filesep 'CoilSimuAttr.xml']);

guidata(hObject, handles);

% --- Executes on button press in CopSelNode_pushbutton.
function CopNode_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to CopSelNode_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

import javax.swing.*
import javax.swing.tree.*;

try
    switch handles.CoilNode.Name
        case 'MRiLabCoil'
            errordlg('MRiLabCoil Root can not be copied!');
            return;
    end
    handles.CopSelNode=handles.SelNode.clone;
    handles.CopCoilNode=handles.CoilNode;
    guidata(hObject, handles);
catch me
    error_msg{1,1}='ERROR!!! Node operation aborted.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);

end

% --- Executes on button press in PasNode_pushbutton.
function PasNode_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to PasNode_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

import javax.swing.*
import javax.swing.tree.*;

try
    switch handles.CoilNode.Name
        case {'MRiLabCoil'}
            % paste node
            handles.CoilTreeModel.insertNodeInto(handles.CopSelNode,handles.SelNode,handles.SelNode.getChildCount());
            handles.CoilTree.setSelectedNode(handles.CopSelNode); % expand to show added child
            handles.CoilTree.setSelectedNode(handles.SelNode); % insure additional nodes are added to parent

            nP=handles.CopSelNode.getPreviousSibling;
            if ~isempty(nP)
                Level=nP.getValue;
                handles.CopSelNode.setValue([Level; Level(end)+1]);
                eval([handles.CoilNodeLvl '.Children(' num2str(Level(end)+1) ')=handles.CopCoilNode;']);
                DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
            else
                nP=handles.CopSelNode.getParent;
                Level=nP.getValue;
                handles.CopSelNode.setValue([Level; 1]);
                eval([handles.CoilNodeLvl '.Children=handles.CopCoilNode;']);
                DoWriteXML(handles.CoilStruct,handles.CoilXMLFile);
            end
        otherwise
            errordlg(['Coil Element can not be added under ' handles.CoilNode.Name '!']);
            return;
    end
    handles.CopSelNode=[];
    handles.CopCoilNode=[];
    guidata(hObject, handles);
catch me
    error_msg{1,1}='ERROR!!! Node operation aborted.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);

end

% --- Executes on button press in CoilExecute_pushbutton.
function CoilExecute_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to CoilExecute_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

set(hObject,'Enable','off');
set(hObject,'String','Calc...');
pause(0.01);
try
    DoPlotCoilSen(handles);
    set(handles.Undock_pushbutton,'Enable','on');
    set(handles.Display_pushbutton,'Enable','on');
    set(handles.Forwards_pushbutton,'Enable','on');
    set(handles.Backwards_pushbutton,'Enable','on');
catch me
    error_msg{1,1}='Error occurred at calculating B1/E1 field.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);
    set(handles.Undock_pushbutton,'Enable','off');
    set(handles.Display_pushbutton,'Enable','off');
    set(handles.Forwards_pushbutton,'Enable','off');
    set(handles.Backwards_pushbutton,'Enable','off');
end
set(hObject,'Enable','on');
set(hObject,'String','Execute');

% --------------------------------------------------------------------
function SavePanel_uipushtool_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to SavePanel_uipushtool (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
DoSaveSnapshot(handles.CoilDesignPanel_figure);

% --- Executes when user attempts to close CoilDesignPanel_figure.
function CoilDesignPanel_figure_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to CoilDesignPanel_figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

clear global VCco;
% Hint: delete(hObject) closes the figure
delete(hObject);

% --- Executes on button press in Forwards_pushbutton.
function Forwards_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Forwards_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global VObj;
TAttr=get(handles.Attrh2.('Plane'),'String');
switch TAttr{get(handles.Attrh2.('Plane'),'Value')}
    case 'XY'
        handles.IV.zslice=handles.IV.zslice+VObj.ZDimRes;
    case 'XZ'
        handles.IV.yslice=handles.IV.yslice+VObj.YDimRes;
    case 'YZ'
        handles.IV.xslice=handles.IV.xslice+VObj.XDimRes;
end
DoUpdateSlice(handles.CoilSen_axes,handles.F,handles.IV,'Coil');
guidata(hObject, handles);

% --- Executes on button press in Backwards_pushbutton.
function Backwards_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Backwards_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global VObj;
TAttr=get(handles.Attrh2.('Plane'),'String');
switch TAttr{get(handles.Attrh2.('Plane'),'Value')}
    case 'XY'
        handles.IV.zslice=handles.IV.zslice-VObj.ZDimRes;
    case 'XZ'
        handles.IV.yslice=handles.IV.yslice-VObj.YDimRes;
    case 'YZ'
        handles.IV.xslice=handles.IV.xslice-VObj.XDimRes;
end
DoUpdateSlice(handles.CoilSen_axes,handles.F,handles.IV,'Coil');
guidata(hObject, handles);

% --------------------------------------------------------------------
function Cursor_uitoggletool_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to Cursor_uitoggletool (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

if ~isfield(handles,'dcm')
    handles.dcm=datacursormode(handles.CoilDesignPanel_figure);
    datacursormode on
    set(handles.dcm,'updatefcn',{@Cursor_update,handles});
else
    if strcmp(get(handles.dcm,'Enable'),'on')
        set(handles.dcm,'Enable','off');
    else
        set(handles.dcm,'Enable','on');
    end
end
guidata(hObject, handles);

function output_txt = Cursor_update(obj,event_obj,handles)
% Display the position of the data cursor
% obj          Currently not used (empty)
% event_obj    Handle to event object
% output_txt   Data cursor text string (string or cell array of strings).

global VObj;
global VCtl;
global VMco;

handles=guidata(handles.CoilDesignPanel_figure);
pos = get(event_obj,'Position');
pos(1)=round((pos(1)+VCtl.ISO(1)*VObj.XDimRes)/VMco.xdimres);
pos(2)=round((pos(2)+VCtl.ISO(2)*VObj.YDimRes)/VMco.ydimres);
pos(3)=round((pos(3)+VCtl.ISO(3)*VObj.ZDimRes)/VMco.zdimres);

output_txt = {['X: ',num2str(pos(1),4)],...
    ['Y: ',num2str(pos(2),4)],...
    ['Z: ',num2str(pos(3),4)],...
    ['Value: ',num2str(handles.F(pos(2),pos(1),pos(3)),4)]};

% --- Executes on button press in Undock_pushbutton.
function Undock_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Undock_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global VMco;
TAttr=get(handles.Attrh2.('Plane'),'String');
switch TAttr{get(handles.Attrh2.('Plane'),'Value')}
    case 'XY'
        zmax=max(VMco.zgrid(1,1,:));
        zmin=min(VMco.zgrid(1,1,:));
        zslice=handles.IV.zslice;
        if zslice<zmax & zslice>zmin
            zslice=floor((zslice-zmin)/VMco.zdimres)+1;
            figure;
            quiver(VMco.xgrid(:,:,zslice),VMco.ygrid(:,:,zslice),handles.Fx(:,:,zslice),handles.Fy(:,:,zslice));
            title('Field direction in XY plane');
            set(gca,'YDir','reverse');
            xlabel('X');  ylabel('Y');
            axis image;
        end
    case 'XZ'
        ymax=max(max(max(VMco.ygrid)));
        ymin=min(min(min(VMco.ygrid)));
        yslice=handles.IV.yslice;
        if yslice<ymax & yslice>ymin
            yslice=floor((yslice-ymin)/VMco.ydimres)+1;
            figure;
            quiver(VMco.xgrid(yslice,:,:),VMco.zgrid(yslice,:,:),handles.Fx(yslice,:,:),handles.Fz(yslice,:,:));
            title('Field direction in XZ plane');
            set(gca,'YDir','reverse');
            xlabel('X');  ylabel('Z');
            axis image;
        end
    case 'YZ'
        xmax=max(max(max(VMco.xgrid)));
        xmin=min(min(min(VMco.xgrid)));
        xslice=handles.IV.xslice;
        if xslice<xmax & xslice>xmin
            xslice=floor((xslice-xmin)/VMco.xdimres)+1;
            figure;
            quiver(VMco.ygrid(:,xslice,:),VMco.zgrid(:,xslice,:),handles.Fy(:,xslice,:),handles.Fz(:,xslice,:));
            title('Field direction in YZ plane');
            set(gca,'YDir','reverse');
            xlabel('Y');  ylabel('Z');
            axis image;
        end
end

% --------------------------------------------------------------------
function NewCoil_uimenu_Callback(hObject, eventdata, handles)
% hObject    handle to NewCoil_uimenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function NewCoilFile_uimenu_Callback(hObject, eventdata, handles)
% hObject    handle to NewCoilFile_uimenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

prompt = {'Enter NEW coil name:','Enter NEW coil note:'};
dlg_title = 'Input for creating new coil';
num_lines = 1;
def = {'Coil_0ChHead','0 Chanel Head Coil'};
answer = inputdlg(prompt,dlg_title,num_lines,def);
if isempty(answer)
    warndlg('No new coil file is created!');
    return
end
if isempty(answer{1})
    warndlg('No new coil file is created!');
    return
end
if ~strcmp(answer{1}(1:5),'Coil_')
    warndlg('Coil name must have a prefix ''Coil_'', please rename your coil!');
    return
end
coilpath=uigetdir(pwd,'Specify a saving path for new coil file.');
if coilpath==0
    warndlg('You have to specify a saving path!');
    return;
end

% Create new coil file
mkdir([coilpath filesep answer{1}]); % make folder
copyfile([handles.Simuh.MRiLabPath filesep 'Config' filesep 'Coil' filesep 'Head' filesep 'Coil_1ChHead' filesep 'Coil_1ChHead.xml'],...
    [coilpath filesep answer{1} filesep answer{1} '.xml']); % copy coil temple
% Add searchig path
path(path,[coilpath filesep answer{1}]);
% Load new coil file
import javax.swing.*;
import javax.swing.tree.*;
if ~isempty(handles.Attrh1)
    Attrh1name=fieldnames(handles.Attrh1);
    for i=1:length(Attrh1name)
        delete(handles.Attrh1.(Attrh1name{i}));
    end
    handles.Attrh1=[];
end
handles.CoilStruct=DoParseXML([coilpath filesep answer{1} filesep answer{1} '.xml']);
for i=1:length(handles.CoilStruct.Attributes)
    if strcmp(handles.CoilStruct.Attributes(i).Name,'Name')
        handles.CoilStruct.Attributes(i).Value = answer{1};
    elseif strcmp(handles.CoilStruct.Attributes(i).Name,'Notes')
        handles.CoilStruct.Attributes(i).Value = answer{2};
    end
end
DoWriteXML(handles.CoilStruct,[coilpath filesep answer{1} filesep answer{1} '.xml']); %update new coil file
handles.CoilXMLFile=[coilpath filesep answer{1} filesep answer{1} '.xml'];
DoWriteXML2m(handles.CoilStruct,[handles.CoilXMLFile(1:end-3) 'm']);
guidata(hObject, handles);
Root=DoConvStruct2Tree(handles.CoilStruct);
handles.CoilTree=uitree('V0','Root',Root,'SelectionChangeFcn', {@ChkNode,handles});
set(handles.CoilTree.getUIContainer,'Units','normalized');
set(handles.CoilTree.getUIContainer,'Position',[0.205,0.4,0.2,0.58]);
handles.CoilTreeModel=DefaultTreeModel(Root);
handles.CoilTree.setModel(handles.CoilTreeModel);
cla(handles.CoilSen_axes);
clear global VCco;
guidata(hObject, handles);

% --- Executes on mouse press over figure background, over a disabled or
% --- inactive control, or over an axes background.
function CoilDesignPanel_figure_WindowButtonDownFcn(hObject, eventdata, handles)
% hObject    handle to CoilDesignPanel_figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

tempaxes = gca;
try
    if strcmp(get(gcf,'Selectiontype'),'alt')
        figure 			% Create a new figure
        ax_new = axes;
        copyaxes(tempaxes, ax_new);
    end
catch me
end

% --- Executes on button press in Display_pushbutton.
function Display_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to Display_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

Conts=get(handles.Attrh2.FieldType,'String');
SelCont=Conts{get(handles.Attrh2.FieldType,'Value')};
switch SelCont
    case 'B1Field'
        Conts=get(handles.Attrh2.Mode,'String');
        SelCont=Conts{get(handles.Attrh2.Mode,'Value')};
        assignin('base', ['B1_' SelCont], handles.F);
        MU_Matrix_Display(['B1_' SelCont],'Magnitude');
    case 'E1Field'
        assignin('base', 'E1_Magnitude', handles.F);
        MU_Matrix_Display('E1_Magnitude','Magnitude');
end


%ISURF SURF feature extractor
%
% SF = ISURF(IM, OPTIONS) returns a vector of SurfPointFeature objects
% representing scale and rotationally invariant interest points in the
% image IM.
%
% The SurfPointFeature object has many properties including:
%  u            horizontal coordinate
%  v            vertical coordinate
%  strength     feature strength
%  descriptor   feature descriptor (64x1 or 128x1)
%  sigma        feature scale
%  theta        feature orientation [rad]
%
% Options::
% 'nfeat',N      set the number of features to return (default Inf)
% 'thresh',T     set Hessian threshold.  Increasing the threshold reduces
%                the number of features computed and reduces computation time.
% 'octaves',N    number of octaves to process (default 5)
% 'extended'     return 128-element descriptor (default 64)
% 'upright'      don't compute rotation invariance
% 'suppress',R   set the suppression radius (default 0).  Features are not
%                returned if they are within R [pixels] of an earlier (stronger)
%                feature.
% Example::
%
% Load the image
%         im = iread('lena.pgm');
% Find the 10 strongest SURF features
%         sf = isurf(im, 'nfeat', 10);
% and overlay them on the original image as blue circles
%         idisp(im);
%         sf.plot_scale()
%
% Notes::
% - Color images, or sequences, are first converted to greyscale.
% - Features are returned in descending strength order
% - If IM is HxWxN it is considered to be an image sequence and F is a cell
%   array with N elements, each of which is the feature vectors for the
%   corresponding image in the sequence.
% - Wraps an M-file implementation of OpenSurf by D. Kroon (U. Twente) or
%   a MEX-file OpenCV wrapper by Petter Strandmark.
% - The sign of the Laplacian is not retained.
% - The SURF algorithm is covered by an extensive suite of international
%   patents including US 8,165,401, EP 1850270 held by Toyota, KU Leuven
%   and ETHZ.  See http://www.kooaba.com/en/plans_and_pricing/ip_licensing
%
% Reference::
% "SURF: Speeded Up Robust Features",
% Herbert Bay, Andreas Ess, Tinne Tuytelaars, Luc Van Gool,
% Computer Vision and Image Understanding (CVIU),
% Vol. 110, No. 3, pp. 346--359, 2008
%
%
% See also SurfPointFeature, ISIFT, ICORNER.

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.

function features = isurf(im, varargin)

    opt.suppress = 0;
    opt.nfeat = Inf;
    opt.extended = true;
    opt.upright = false;
    opt.octaves = 5;
    opt.thresh = [];
    opt.id = [];

    [opt,arglist] = tb_optparse(opt, varargin);

    if iscell(im)
        % images provided as a cell array, return a cell array
        % of SURF object vectors
        fprintf('extracting SIFT features for %d greyscale images\n', length(im));
        features = {};
        for i=1:length(im)
            sf = isurf(im{i}, 'setopt', opt, 'id', i);

            features{i} = sf;
            fprintf('.');
        end
        fprintf('\n');
        return
    end

    % convert color image to greyscale
    if iscolor(im)
       im = imono(im);
    end

    if ndims(im) > 2

        % TODO sequence of color images..

        % images provided as an array, return a cell array
        % of SURF object vectors
        if opt.verbose
            fprintf('extracting SURF features for %d greyscale images\n', size(im,3));
        end
        features = {};
        for i=1:size(im,3)
            sf = isurf(im(:,:,i), 'setopt', opt);
            for j=1:length(sf)
                sf(j).image_id_ = i;
            end
            features{i} = sf;
            fprintf('.');
        end
        if opt.verbose
            fprintf('\n');
        end
        return
    end

    % do SURF using a static method that wraps the implementation from:
    % OpenSURF for Matlab
    %   written by D.Kroon University of Twente (July 2010)
    %   based on the C++ implementation by Chris Evans
    %try  HACK
        Ipts = SurfPointFeature.surf(im, opt);
%     catch
%         error('Contributed software [OpenSurf] for SURF features is not installed');
%     end

    % Ipts is a structure array with elements x, y, scale, orientation, descriptor

    try
        % sort into descending order of corner strength
        [z,k] = sort([Ipts.strength], 'descend');
        Ipts = Ipts(:,k);
    catch
        % will fail if no features found
        features = [];
        return;
    end

    fprintf('%d corners found (%.1f%%), ', length(Ipts), ...
        length(Ipts)/prod(size(im))*100);

    % allocate storage for the objects
    n = min(opt.nfeat, length(Ipts));

    features = [];
    i = 1;
    while i<=n
        if i > length(Ipts)
            break;
        end

        % enforce separation between corners
        % TODO: strategy of Brown etal. only keep if 10% greater than all within radius
        if (opt.suppress > 0) && (i>1)
            d = sqrt( ([features.v]'-Ipts(i).y).^2 + ([features.u]'-Ipts(i).x).^2 );
            if min(d) < opt.suppress
                continue;
            end
        end
        f = SurfPointFeature(Ipts(i).x, Ipts(i).y, Ipts(i).strength);
        f.scale_ = Ipts(i).scale;
        f.theta_ = Ipts(i).orientation;
        f.descriptor_ = cast(Ipts(i).descriptor, 'single');
        f.image_id_ = opt.id;

        features = [features f];
        i = i+1;
    end
    fprintf(' %d corner features saved\n', i-1);


function colors = prtPlotUtilClassColorsBW(nClasses)
% Internal function, default color specs.
% xxx Need Help xxx

% colors = [55  126 184; % Blue
%           228 26  28;  % Red
%           77  175 74;  % Green
%           255 127 0;   % Orange
%           153 153 153; % Gray
%           166 86  40;  % Brown
%           152 78  163; % Purple
%           255 255 51;  % Yello
%           247 129 191; % Pink
%           ]/255;

%255, 255, 191;
colors = [215,  25,  28;
          253, 174,  97;
          171, 221, 164;
           43, 131, 186;]/255;

% colors = gray(5);
% colors = colors(1:4,:);

colorMapInd = repmat((1:size(colors,1))',ceil(nClasses/size(colors,1)),1);
colorMapInd = colorMapInd(1:nClasses);

colors = colors(colorMapInd,:);


function lvmResultsClick(modelType, dataSet, number, dataType, varargin)

% LVMRESULTSCLICK Load a results file and visualise them with clicks
% FORMAT
% DESC loads results of a latent variable model and visualises them.
% ARG modelType : the type of model ran on the data set.
% ARG dataSet : the name of the data set to load.
% ARG number : the number of the run used.
% ARG dataType : the type of data to visualise.
% ARG arg1, arg2, arg3 ... : additional arguments to be passed to the
% lvmVisualise command.
%
% SEEALSO : lvmLoadResult, lvmVisualise
%
% COPYRIGHT : Neil D. Lawrence, 2008, 2009

% MLTOOLS

[model, lbls] = lvmLoadResult(modelType, dataSet, number);

% Visualise the results
switch size(model.X, 2)
 case 2
  lvmClickVisualise(model, lbls, [dataType 'Visualise'], [dataType 'Modify'], ...
                 varargin{:});

 otherwise
  lvmClickVisualise(model, lbls, [dataType 'Visualise'], [dataType 'Modify'], ...
                 varargin{:});
end


function [volInfo, dat] = iimg_read_img(inputimgs, extended_output_flag, reading_data, first_vol)
% :Usage:
% ::
%
%     [volInfo, dat] = iimg_read_img(inputimgs, [extended_output_flag (1|2)], [reading_data (0|1)], [first vol only (0|1)]);
%
% - reads 3-D or 4-D img/nii files, with extended volInfo output
% - flag to read first volume only
% - can read iimg_data vectorized form as well as file names (just passes dat to output)
% - uses SPM
%
% volInfo fields:
%   - all fields returned by spm_vol, plus:
%   - .nvox - number of voxels in 3d image
%  - .image_indx - logical index (e.g., [0 1 1 0 1 ...]) of all nonzero voxels
%  - .wh_inmask (extended_output_flag > 0) - linear index (e.g., [2 3 5 ...]) - same as image_indx, but as a result of find
%  - .n_inmask (extended_output_flag > 0) - length of .wh_inmask
%  - .xyzlist (extended_output_flag > 0) - voxel coords of .wh_inmask voxels
%  - .cluster (extended_output_flag > 1) - cluster structure of in-mask voxels
%
% Extended output flag values:
%   1: Add xyz coord list and linear index of which voxels nonzero & non-nan in mask
%   2: Add clusters from spm_clusters
%
% Enforces that dat is a vector of data values, regardless of input.
%
% :Examples:
% ::
%
%    imname = 'rob_tmap_0001_filt_t_3-05_k5_pos.img';
%    volInfo = iimg_read_img(imname);
%
% WARNING:
% The behavior of this function is SPM version dependent.
% volInfo only contains the spm_vol structure of the FIRST image!!!
% Data in SPM5/8 should be 4-D, but in SPM2 should be 3-D
%
% Example of image reading/writing
% -------------------------------------------------------------------------
%   1) Get volume info from first volume of a 3-D or 4-D image
%       volInfo structure has necessary info for converting to/from
%       "vectorized" format
%       dat returns 4-D data from entire image (all volumes)
%       ::
%
%           iimg_name = 'test_run1_pca.img';
% [maskInfo, dat] = iimg_read_img(img_name, 2);
%
%   2) Get data in "vectorized" image format for each volume in the
%      image. Works for a list of images too. data is in-mask voxels x volumes
%      this can be useful when you want to return whole-brain data for many
%      images, but in a search volume only (i.e., no extra-brain voxels)
%      ::
%
%           idata = iimg_get_data(maskInfo, img_name);
%           data = data';  % make sure columns are volumes
%
% % 3) Write out a 4-D image with the same data, called test_run1_pca2.img
%       ::
%
%           ivoldat3D = iimg_reconstruct_vols(data, maskInfo, 'outname',
%                                                 'test_run1_pca2.img');

% ..
%    Set up arguments
% ..
if ~exist('inputimgs', 'var') || isempty(inputimgs)

    error('Input image not found. Check file and path names.');

end

if ~exist('extended_output_flag', 'var') || isempty(extended_output_flag)
    extended_output_flag = 0;
end
if ~exist('reading_data', 'var') || isempty(reading_data)
    reading_data = 1;
end

if ~exist('first_vol', 'var') || isempty(first_vol)
    first_vol = 0;
end

if(~reading_data && extended_output_flag)
    warning('If not reading in file data, the extended_output_flag has no meaning');
end

imgtype = get_img_type(inputimgs);

volInfo = [];
num_imgs = size(inputimgs, 1);
if first_vol, num_imgs = 1; end

switch imgtype
    case 'name'
        % ---------------------------------------------------------------
        % * String matrix of filenames: Load first volume, then all data
        % ---------------------------------------------------------------
        % use iimg_read_from_file

        space_defining_image = inputimgs(1, :);

%         if first_vol
%             whcomma = find(space_defining_image == ',');
%             if ~isempty(whcomma)
%                 space_defining_image = space_defining_image(1:whcomma-1);
%             end
%
%             space_defining_image = [space_defining_image ',1'];
%
%         end

        % Read first image, or first set of volumes in 4-d file:
        % If firstvol, the ",1" will be added to space defining image after
        % (possible) unzipping and checks on whether it exists.

        [volInfo, dat] = iimg_read_from_file(space_defining_image, extended_output_flag, reading_data, first_vol);

        if(reading_data && num_imgs > 1)
            % load other images; check to make sure they're in same dims as first

            dat = [dat zeros(volInfo.nvox, num_imgs-1)];

            for i = 2:num_imgs
                [indx data] = iimg_read_from_file(inputimgs(i, :), 0, reading_data, 0); % read all, not just first vol

                if length(data) ~= volInfo.nvox
                    fprintf('Warning: img dims for %s do not match 1st image. Resampling.\n', inputimgs(i, :));

                    data = scn_map_image(inputimgs(i, :), inputimgs(1, :));
                    data = data(:);

                end

                dat(:, i) = data;
            end
        end

    case '3dvols'
        % --------------------------------------
        % * matrix of 3-D image data volumes
        % --------------------------------------

        [x, y, z, n] = size(inputimgs);
        nvox = prod(x, y, z);
        dat = zeros(nvox, n);

        for i = 1:num_imgs
            tmp = inputimgs(:, :, :, i);
            dat(:, i) = tmp(:);
        end

        dat(isnan(dat)) = 0;

    case 'indx'
        % --------------------------------------
        % * Already in index -- target format
        % --------------------------------------
        dat = inputimgs;
end
end

function imgtype = get_img_type(inputimgs)
if ischar(inputimgs)
    imgtype = 'name';

    return
end

[x, y, z] = size(inputimgs);

if isa(inputimgs, 'statistic_image')
    imgtype = 'statistic_image';
elseif z > 1
    % 3-D image(s)
    imgtype = '3dvols';
elseif x > 1
    % voxels x images 2-D index matrix
    imgtype = 'indx';
else
    error('I don''t recognize the data format of inputimgs.');
end
end

% iimg_read_from_file
% -------------------------------------------------------------------------

function [volInfo, dat] = iimg_read_from_file(imname, extended_output_flag, reading_data, dofirstvolonly)
% Read image data from file using spm_vol and spm_read_vols.
% Call vol_file_check, which checks zipped and unzipped versions and
% gunzips if needed

% Returns filename for unzipped image with formatting ,# to read first vol
% only if requested
imname = vol_file_check(imname, dofirstvolonly);

% %  tor: oct 2010: speed up by adding ,1 to get only first vol in spm
% [pth, nam, ext] = fileparts(imname);
% wh_comma = find(ext == ',');
% if isempty(wh_comma)
%     imname = [imname ',1'];
% end

volInfo = spm_vol(imname);

% Changed Feb 2008 to deal with 4-D image reading in SPM5 and above
nimgs = length(volInfo);

for i = 1:nimgs
    volInfo(i).nvox = prod(volInfo(i).dim(1:3));
end

dat = [];

if(reading_data)

    switch spm('Ver')
        case 'SPM2'
            % spm_defaults is a script
            disp('WARNING: spm defaults not set for spm2. Make sure your defaults are set correctly');

        case {'SPM5', 'SPM8', 'SPM12'}
            % spm_defaults is a function
            spm_defaults()

        otherwise
            % unknown SPM
            disp('Unknown version of SPM!');
            spm_defaults()
    end

    % pre-allocate array
    dat = zeros(volInfo(1).nvox, nimgs);

    for i = 1:nimgs

        dat_vol = spm_read_vols(volInfo(i));
        dat(:, i) = dat_vol(:);

        volInfo(i).image_indx = dat(:) ~= 0; % locate all voxels in-mask

    end

    if extended_output_flag
        % Return this for first image only right now.
        volInfo(1).wh_inmask = find(volInfo(1).image_indx);    % indices of all voxels in mask

        volInfo(1).n_inmask = size(volInfo(1).wh_inmask, 1);

        [i, j, k] = ind2sub(volInfo(1).dim(1:3), volInfo(1).wh_inmask);
        volInfo(1).xyzlist = [i j k];

        if extended_output_flag > 1
            if volInfo(1).n_inmask < 50000
                volInfo(1).cluster = spm_clusters(volInfo(1).xyzlist')';
            else
                volInfo(1).cluster = ones(volInfo(1).n_inmask, 1);
            end
        end
    end

    dat(isnan(dat)) = 0;
end

% Return only the first volInfo struture because it contains generic info
% about all volumes.  Don't need to return every volume for our
% purposes.
volInfo = volInfo(1);

end

function [imname, waszipped] = vol_file_check(imname, varargin)
% Check that filename exists, in either gz (zipped) or unzipped format, and
% return file name of file with full path name.
% If both zipped and unzipped exist, prefer unzipped.
% Return flag waszipped so file can be re-zipped after loading.

waszipped = false;

if length(varargin) > 0
    dofirstvolonly = varargin{1};
end

if(~ischar(imname) || isempty(imname))
    error('Image name is not string or is empty.');
end

imname = deblank(imname);

% strip ,# volume numbers sometimes added by SPM
imname = regexprep(imname, ',\w*', '');

% strip .gz version for now and create .gz and non-.gz version. check for both.
imname = regexprep(imname, '.gz', '');

gzipexists = exist([imname '.gz'], 'file');
nozipexists = exist(imname, 'file');

if nozipexists
    % use imname

elseif gzipexists
    % use .gz - unzip and use previous value of imname
    % flag for re-gzipping later.
    waszipped = true;
    system(['gunzip ' imname '.gz']);

else
    error('Image "%s" does not exist or cannot be found on path (unzipped or .gz versions)!', imname);
end

full_imname = which(imname); % sometimes ok, sometimes empty if full path already included

if exist(full_imname, 'file') % if not empty and ok, else default to previous value of imname
    imname = full_imname;
end

% Add volume number if first vol only
if dofirstvolonly

    imname = [imname ',1'];

end

end


%% positive integer dumping
if dumpmsgpack(int8(0)) ~= uint8(0)
    error('Dumping 0 failed')
end
if any(dumpmsgpack(uint8(1)) ~= uint8(1))
    error('Dumping positive fixnum failed')
end
if any(dumpmsgpack(uint8(128)) ~= uint8([204, 128]))
    error('Dumping uint8  failed')
end
if any(dumpmsgpack(uint16(256)) ~= uint8([205, 1, 0]))
    error('Dumping uint16 failed')
end
if any(dumpmsgpack(uint32(2^16)) ~= uint8([206, 0, 1, 0, 0]))
    error('Dumping uint32 failed')
end
if any(dumpmsgpack(uint64(2^32)) ~= uint8([207, 0, 0, 0, 1, 0, 0, 0, 0]))
    error('Dumping uint64 failed')
end

%% negative integer dumping
if dumpmsgpack(int8(-1)) ~= uint8(255)
    error('Dumping negative fixnum failed')
end
if any(dumpmsgpack(int8(-128)) ~= uint8([208, 128]))
    error('Dumping int8  failed')
end
if any(dumpmsgpack(int16(-256)) ~= uint8([209, 255, 0]))
    error('Dumping int16 failed')
end
if any(dumpmsgpack(int32(-2^16)) ~= uint8([210, 255, 255, 0, 0]))
    error('Dumping int32 failed')
end
if any(dumpmsgpack(int64(-2^32)) ~= uint8([211, 255, 255, 255, 255, 0, 0, 0, 0]))
    error('Dumping int64 failed')
end

%% float dumping
if any(dumpmsgpack(single(1.5)) ~= uint8([202, 63, 192, 0, 0]))
    error('Dumping float32 failed')
end
if any(dumpmsgpack(double(1.5)) ~= uint8([203, 63, 248, 0, 0, 0, 0, 0, 0]))
    error('Dumping float64 failed')
end

%% string dumping
if any(dumpmsgpack('foo') ~= uint8([163, 102, 111, 111]))
    error('Dumping fixstr failed')
end
if any(dumpmsgpack(repmat('a', [1, 32])) ~= uint8([217, 32, ones(1, 32)*'a']))
    error('Dumping str8 failed')
end
if any(dumpmsgpack(repmat('a', [1, 2^8])) ~= uint8([218, 1, 0, ones(1, 2^8)*'a']))
    error('Dumping str16 failed')
end
if any(dumpmsgpack(repmat('a', [1, 2^16])) ~= uint8([219, 0, 1, 0, 0, ones(1, 2^16)*'a']))
    error('Dumping str16 failed')
end

%% bin dumping
if any(dumpmsgpack(repmat(uint8(42), [1, 32])) ~= uint8([196, 32, ones(1, 32)*42]))
    error('Dumping str8 failed')
end
if any(dumpmsgpack(repmat(uint8(42), [1, 2^8])) ~= uint8([197, 1, 0, ones(1, 2^8)*42]))
    error('Dumping str16 failed')
end
if any(dumpmsgpack(repmat(uint8(42), [1, 2^16])) ~= uint8([198, 0, 1, 0, 0, ones(1, 2^16)*42]))
    error('Dumping str16 failed')
end

%% array dumping
if any(dumpmsgpack({uint8(1), uint8(2)}) ~= uint8([146, 1, 2]))
    error('Dumping fixarray failed')
end
if any(dumpmsgpack(num2cell(repmat(uint8(42), [1, 16]))) ~= uint8([220, 0, 16, repmat(42, [1, 16])]))
    error('Dumping array16 failed')
end
% takes too long:
% if any(dumpmsgpack(num2cell(repmat(uint8(42), [1, 2^16]))) ~= uint8([221, 0, 1, 0, 0 repmat(42, [1, 2^16])]))
%     error('Dumping array32 failed')
% end

%% map dumping
if any(dumpmsgpack(struct('one', uint8(1), 'two', uint8(2))) ~= uint8([130, dumpmsgpack('one'), 1, dumpmsgpack('two'), 2]))
    error('Dumping fixmap failed')
end
data = struct();
msgpack = uint8([]);
for n=[1 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9] % default struct field order
    data.(['x' num2str(n)]) = uint8(n);
    msgpack = [msgpack dumpmsgpack(['x' num2str(n)]) uint8(n)];
end
if any(dumpmsgpack(data) ~= uint8([222, 0, 16, msgpack]))
    error('Dumping map16 failed')
end
% map32 takes too long


%  logisticn nth-order logistic function
%
%  ::
%
%
%  Args:
%
%  Returns:
%     :
%
%  Note:
%
%  Example:
%
%     See also:
%


function obj_size_print ( input_file_name, node_num, face_num, normal_num, ...
  order_max )

%*****************************************************************************80
%
%% OBJ_SIZE_PRINT prints sizes associated with an OBJ file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Input, integer NODE_NUM, the number of vertices defined.
%
%    Input, integer FACE_NUM, the number of faces defined.
%
%    Input, integer NORMAL_NUM, the number of normal vectors defined.
%
%    Input, integer ORDER_MAX, the maximum number of vertices per face.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Object sizes for OBJ file "%s":\n', input_file_name );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Nodes              = %d\n', node_num );
  fprintf ( 1, '  Faces              = %d\n', face_num );
  fprintf ( 1, '  Maximum face order = %d\n', order_max );
  fprintf ( 1, '  Normal vectors     = %d\n', normal_num );

  return
end


%% cell get_algorithms_list(int)
%
function [alg_list] = get_algorithm_list(id)
  L = load_algorithm_list();
  [m,~] = size(L{1,1});
  alg_list = {};
  k = 1;
  for i = 1 : m
    method_id_field = char(L{1,1}(i));
    method_id_list = strsplit(method_id_field,',');

    [~,s] = size(method_id_list);

    flag = 0;
    for j = 1 : s
      method_id = strtrim(char(method_id_list{1,j}));
      if(strcmp(method_id,'-'))
        alg_list{k,1} = '-';
        alg_list{k,2} = '-';
        alg_list{k,3} = 0;
        alg_list{k,4} = '-';
        k = k + 1;
        break;
      end
%       if(method_id(1) == '-')
%         list{i,1} = '-';
%         break;
%       end
      if(strcmp(id,method_id))
        flag = 1;
      end
    end

    if(flag == 0)
      continue;
    end

    algorithm_id = strtrim(char(L{1,2}(i)));
    algorithm_name = strtrim(char(L{1,3}(i)));

    algorithm = [algorithm_id ' ' algorithm_name];

    alg_list{k,1} = algorithm_id;
    alg_list{k,2} = algorithm_name;
    alg_list{k,3} = L{1,4}(i);
    alg_list{k,4} = algorithm;
    k = k + 1;
  end
end


function D = spm_eeg_ft_artefact_visual(S)
% Function for interactive artefact rejection using Fieldtrip
%
% Disclaimer: this code is provided as an example and is not guaranteed to work
% with data on which it was not tested. If it does not work for you, feel
% free to improve it and contribute your improvements to the MEEGtools toolbox
% in SPM (http://www.fil.ion.ucl.ac.uk/spm)
%
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: spm_eeg_ft_artefact_visual.m 5674 2013-10-09 10:00:26Z vladimir $

[Finter,Fgraph,CmdLine] = spm('FnUIsetup', 'Fieldtrip visual artefact rejection',0);

if nargin == 0
    S = [];
end

try
    D = S.D;
catch
    D = spm_select(1, '\.mat$', 'Select EEG mat file');
    S.D = D;
end

if ischar(D)
    try
        D = spm_eeg_load(D);
    catch
        error(sprintf('Trouble reading file %s', D));
    end
end

if isequal(D.type, 'continuous')
    error('Artefact detection can only be applied to epoched data');
end

trlind = find(~badtrials(D, ':'));

data = ftraw(D, ':', ':', trlind);

data.trialinfo = [1:length(trlind)]';

cfg=[];

if isfield(S, 'method')
    cfg.method = S.method;
else
    cfg.method =  spm_input('What method?','+1', 'm', 'summary|channel|trial', strvcat('summary', 'channel', 'trial'));
end

if isfield(S, 'latency')
    cfg.latency = S.latency;
else
    cfg.latency = 1e-3*spm_input('PST ([start end] in ms):', '+1', 'r', num2str(1e3*[data.time{1}(1) data.time{1}(end)]), 2);
end

cfg.keepchannel = 'no';

if isfield(S, 'channel')
    cfg.channel = S.channel;
else
    [junk, chanind] = spm_eeg_modality_ui(D, 0, 1);
    cfg.channel = data.label(chanind);
end

data = ft_rejectvisual(cfg, data);

% Figure out based on the output of FT function what trials and channels to
% reject
trlsel = ones(1, length(trlind));
trlsel(data.trialinfo (:, 1)) = 0;

D = badtrials(D, trlind, trlsel);

badchan = setdiff(cfg.channel, data.label);
if ~isempty(badchan)
    badchanind = spm_match_str(D.chanlabels, badchan);
    D = badchannels(D, badchanind, 1);
end

if ~isfield(S, 'save') || S.save
    save(D);
end


function varargout = edgesEval( model, varargin )
% Run and evaluate structured edge detector on BSDS500.
%
% This function first runs the trained structured edge detector on every
% test or validation image in BSDS then call edgesEvalDir.m to perform the
% actual edge evaluation. edgesEval is specific to the structured edge
% detector and BSDS, edgesEvalDir is general purpose edge evaluation code.
% For example usage of edgesEval see edgesDemo.
%
% USAGE
%  varargout = edgesEval( model, prms )
%
% INPUTS
%  model      - structured edge model trained with edgesTrain
%  prms       - parameters (struct or name/value pairs)
%   .dataType   - ['test'] should be either 'test' or 'val'
%   .name       - [''] name to append to evaluation
%   .opts       - {} list of model opts to overwrite
%   .show       - [0] if true plot results using edgesEvalPlot
%   .pDistr     - [{'type','parfor'}] parameters for fevalDistr
%   .cleanup    - [0] if true delete temporary files
%   .thrs       - [99] number or vector of thresholds for evaluation
%   .maxDist    - [.0075] maximum tolerance for edge match
%
% OUTPUTS
%  varargout  - same outputs as edgesEvalDir
%
% EXAMPLE
%
% See also edgesDemo, edgesDetect, edgesEvalDir, edgesEvalPlot
%
% Structured Edge Detection Toolbox      Version 3.0
% Copyright 2014 Piotr Dollar.  [pdollar-at-microsoft.com]
% Please email me if you find bugs, or have suggestions or questions!
% Licensed under the MSR-LA Full Rights License [see license.txt]

% get default parameters
dfs={'dataType','test', 'name','', 'opts',{}, 'show',0, ...
  'pDistr',{{'type','parfor'}}, 'cleanup',0, 'thrs',99, 'maxDist',.0075 };
p=getPrmDflt(varargin,dfs,1);

% load model and update model.opts acoording to opts
if( ischar(model) ), model=load(model); model=model.model; end
for i=1:length(p.opts)/2, model.opts.(p.opts{i*2-1})=p.opts{i*2}; end
rgbd=model.opts.rgbd; model.opts.nms=1;

% get list of relevant directories (image, depth, gt, results)
name = [model.opts.modelFnm,p.name];
imgDir = fullfile(model.opts.bsdsDir,'images',p.dataType);
depDir = fullfile(model.opts.bsdsDir,'depth',p.dataType);
gtDir  = fullfile(model.opts.bsdsDir,'groundTruth',p.dataType);
resDir = fullfile(model.opts.modelDir,p.dataType,name);
assert(exist(imgDir,'dir')==7); assert(exist(gtDir,'dir')==7);

% run edgesDetect() on every image in imgDir and store in resDir
if( ~exist(fullfile([resDir '-eval'],'eval_bdry.txt'),'file') )
  if(~exist(resDir,'dir')), mkdir(resDir); end
  ids=dir(imgDir); ids=ids([ids.bytes]>0); ids={ids.name}; n=length(ids);
  ext=ids{1}(end-2:end); for i=1:n, ids{i}=ids{i}(1:end-4); end
  res=cell(1,n); for i=1:n, res{i}=fullfile(resDir,[ids{i} '.png']); end
  do=false(1,n); for i=1:n, do(i)=~exist(res{i},'file'); end
  ids=ids(do); res=res(do); m=length(ids);
  parfor i=1:m, id=ids{i};
    I = imread(fullfile(imgDir,[id '.' ext])); D=[];
    if(rgbd), D=single(imread(fullfile(depDir,[id '.png'])))/1e4; end
    if(rgbd==1), I=D; elseif(rgbd==2), I=cat(3,single(I)/255,D); end
    E=edgesDetect(I,model); imwrite(uint8(E*255),res{i});
  end
end

% perform actual evaluation using edgesEvalDir
varargout=cell(1,max(1,nargout));
[varargout{:}] = edgesEvalDir('resDir',resDir,'gtDir',gtDir,...
  'pDistr',p.pDistr,'cleanup',p.cleanup,'thrs',p.thrs,'maxDist',p.maxDist);
if( p.show ), figure(p.show); edgesEvalPlot(resDir,name); end

end


function OutputFiles = db_set_noisecov(iSrcStudy, Target, isDataCov, ReplaceFile)
% DB_SET_NOISECOV: Apply a noise covariance node to other studies
%
% USAGE:  OutputFiles = db_set_noisecov(iSrcStudy, iDestStudies, isDataCov=0, ReplaceFile=[ask])  : Apply to the target studies
%         OutputFiles = db_set_noisecov(iSrcStudy, 'AllConditions')                               : Apply to all the conditons in the same subject
%         OutputFiles = db_set_noisecov(iSrcStudy, 'AllSubjects')                                 : Apply to all the conditons in all the subjects

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2009-2016

% Parse inputs
if (nargin < 4) || isempty(ReplaceFile)
    ReplaceFile = [];
end
if (nargin < 3) || isempty(isDataCov)
    isDataCov = 0;
end
OutputFiles = {};

% ===== GET SOURCE STUDY =====
% Get source study
sSrcStudy = bst_get('Study', iSrcStudy);
% Check for noise covariance matrix
if isempty(sSrcStudy.Channel)
    error('This operation requires that you have a channel file defined in the source and destination studies.');
end
if isempty(sSrcStudy.NoiseCov) || (~isDataCov && isempty(sSrcStudy.NoiseCov(1).FileName)) || (isDataCov && ((length(sSrcStudy.NoiseCov) < 2) || isempty(sSrcStudy.NoiseCov(2).FileName)))
    error('No noise covariance available in the source study.');
end

% ===== GET TARGET STUDIES =====
if isnumeric(Target)
    % Destination studies are passed in argument
    iDestStudies = Target;
elseif strcmpi(Target, 'AllConditions')
    % Get all the studies for this subject
    [sDestStudies, iDestStudies] = bst_get('StudyWithSubject', sSrcStudy.BrainStormSubject);
elseif strcmpi(Target, 'AllSubjects')
    % Get the whole database
    ProtocolSubjects = bst_get('ProtocolSubjects');
    % Get list of subjects (sorted alphabetically => same order as in the tree)
    [uniqueSubjects, iUniqueSubjects] = sort({ProtocolSubjects.Subject.Name});
    % Process each subject
    iDestStudies = [];
    for iSubj = 1:length(uniqueSubjects)
        % Get subject filename
        iSubject = iUniqueSubjects(iSubj);
        SubjectFile = ProtocolSubjects.Subject(iSubject).FileName;
        % Get all the studies for this subject
        [sStudies, iStudies] = bst_get('StudyWithSubject', SubjectFile, 'intra_subject', 'default_study');
        iDestStudies = [iDestStudies, iStudies];
    end
else
    return;
end
% Get the channels studies for those studies
[sDestChannels, iDestChanStudies] = bst_get('ChannelForStudy', iDestStudies);
% Unique list
iDestChanStudies = unique(iDestChanStudies);
% Remove the one the NoiseCov file comes from
iDestChanStudies = setdiff(iDestChanStudies, iSrcStudy);
% If there are no targets
if isempty(iDestChanStudies)
    error('No destination studies.');
end

% ===== READ SOURCE DATA =====
% Load noisecov file
if isDataCov
    SrcNoiseCovMat = load(file_fullpath(sSrcStudy.NoiseCov(2).FileName));
else
    SrcNoiseCovMat = load(file_fullpath(sSrcStudy.NoiseCov(1).FileName));
end
% Load channel file
SrcChannelMat = in_bst_channel(sSrcStudy.Channel.FileName);

% ===== APPLY NOISECOV =====
% Process each target study
for i = 1:length(iDestChanStudies)
    % Get destination study
    iDestStudy = iDestChanStudies(i);
    sDestStudy = bst_get('Study', iDestStudy);
    % If no channel defined: ignore destination channel
    if isempty(sDestStudy.Channel) || isempty(sDestStudy.Channel.FileName)
        disp(['BST> Warning: No channel file in ' bst_fileparts(sDestStudy.FileName) ': Ignoring condition...']);
        continue;
    end
    % Load destination channel file
    DestChannelMat = in_bst_channel(sDestStudy.Channel.FileName);
    % Intialize destination noise covariance matrix
    nbDestChan = length(DestChannelMat.Channel);
    DestNoiseCovMat = SrcNoiseCovMat;
    DestNoiseCovMat.NoiseCov = zeros(nbDestChan);

    % Find the indices of src channels in dest channels
    iSrcChan = [];
    iDestChan = [];
    for iChan = 1:nbDestChan
        iTmp = find(strcmpi({SrcChannelMat.Channel.Name}, DestChannelMat.Channel(iChan).Name));
        if ~isempty(iTmp) && ~isempty(DestChannelMat.Channel(iChan).Name)
            iDestChan(end+1) = iChan;
            iSrcChan(end+1) = iTmp(1);
        end
    end

    % If some channels were the same in both files
    if ~isempty(iDestChan)
        DestNoiseCovMat.NoiseCov(iDestChan,iDestChan) = SrcNoiseCovMat.NoiseCov(iSrcChan,iSrcChan);
        % Other fields
        if isfield(SrcNoiseCovMat, 'FourthMoment') && ~isempty(SrcNoiseCovMat.FourthMoment)
            DestNoiseCovMat.FourthMoment = zeros(nbDestChan);
            DestNoiseCovMat.FourthMoment(iDestChan,iDestChan) = SrcNoiseCovMat.FourthMoment(iSrcChan,iSrcChan);
        end
        if isfield(SrcNoiseCovMat, 'nSamples') && ~isempty(SrcNoiseCovMat.nSamples)
            DestNoiseCovMat.nSamples = zeros(nbDestChan);
            DestNoiseCovMat.nSamples(iDestChan,iDestChan) = SrcNoiseCovMat.nSamples(iSrcChan,iSrcChan);
        end
        % Copy this structure in all the target studies
        NewFile = import_noisecov(iDestStudy, DestNoiseCovMat, ReplaceFile, isDataCov);
        if ~isempty(NewFile) && ischar(NewFile)
            OutputFiles{end+1} = NewFile;
        end
    end
end


% EEG_INSERTBOUND - insert boundary event in an EEG event structure.
%
% Usage:
%       >> [eventout indnew] = eeg_insertbound( eventin, pnts, ...
%                                                abslatency, duration);
% Required Inputs:
%   eventin    - EEGLAB event structure (EEG.event)
%   pnts       - data points in EEG dataset (EEG.pnts * EEG.trials)
%   abslatency - absolute latency of regions in original dataset. Can
%                also be an array of [beg end] latencies with one row
%                per region removed. Then 'lengths' argument is ignored.
% Optional Inputs:
%   lengths    - lengths of removed regions
%
% Outputs:
%   eventout   - EEGLAB event output structure with added boundaries
%   indnew     - array of indices returning new event index for any old
%                (input eventin) event index
% Notes:
%   This function performs the following:
%   1) add boundary events to the 'event' structure;
%        remove nested boundaries;
%        recompute the latencies of all events.
%   2) all latencies are given in (float) data points.
%        e.g., a latency of 2000.3 means 0.3 samples (at EEG.srate)
%              after the 2001st data frame (since first frame has latency 0).
%
% Author: Arnaud Delorme and Hilit Serby, SCCN, INC, UCSD, April, 19, 2004
%
% See also: EEG_EEGREJ, POP_MERGESET

% Copyright (C) 2004 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [eventout,indnew] = eeg_insertboundold( eventin, pnts, regions, lengths)

    if nargin < 3
        help eeg_insertbound;
        return;
    end

    if size(regions,2) ~= 1 && exist('lengths') ~= 1
        lengths = regions(:,2)-regions(:,1)+1;
        regions = regions(:,1);
    end
    if exist('lengths') ~= 1
        lengths = zeros(size(regions));
    end

    % resort events
    if ~isempty(eventin)
        [~,sortedEvents] = sort([eventin.latency]);
        eventin = eventin(sortedEvents);
    end

    if ~isempty(regions)
        fprintf('eeg_insertbound(): %d boundary (break) events added.\n', size(regions, 1));
    else
        return;
    end

    % recompute latencies of boundevents (in new dataset)
    % ---------------------------------------------------
    [regions, tmpsort] = sort(regions);
    lengths            = lengths(tmpsort);
    boundevents        = regions(:,1)-0.5;

    % sort boundevents by decreasing order (otherwise bug in new event index)
    % ------------------------------------
    boundevents = boundevents(end:-1:1);
    lengths     = lengths    (end:-1:1);
    eventout    = eventin;
    indnew      = 1:length(eventin);
    countrm     = 0;
	for tmpindex = 1:length(boundevents) % sorted in decreasing order
        if boundevents(tmpindex) >= 0.5 && boundevents(tmpindex) <= pnts

            % find event succeeding boundary to insert event
            % at the correct location in the event structure
            % ----------------------------------------------
            if ~isempty(eventout) && isfield(eventout, 'latency')
                alllats   = [ eventout.latency ] - boundevents(tmpindex);
                tmpind    = find( alllats >= 0 );
                [~, tmpind2 ] = min(alllats(tmpind));
                tmpind2       = tmpind(tmpind2);
            else
                tmpind2 = [];
            end

            % insert event at tmpind2
            % -----------------------
            if ~isempty(tmpind2)
                eventout(end+1).type = eeg_boundarytype(eventout);
                tmp = eventout(end);
                eventout(tmpind2+1:end) = eventout(tmpind2:end-1);
                eventout(tmpind2) = tmp;
                indnew(tmpind2:end) = indnew(tmpind2:end)+1;
            else
                tmpind2 = length(eventout)+1;
                eventout(tmpind2).type = eeg_boundarytype(eventout);
            end
            eventout(tmpind2).latency  = boundevents(tmpindex);
            eventout(tmpind2).duration = lengths(tmpindex); % just to create field

            [ tmpnest, addlength ] = findnested(eventout, tmpind2);

            % recompute latencies and remove events in the rejected region
            % ------------------------------------------------------------
            eventout(tmpnest) = [];
            countrm           = countrm+length(tmpnest);
            for latind = tmpind2+1:length(eventout)
                eventout(latind).latency = eventout(latind).latency-lengths(tmpindex);
            end

            % add lengths of previous events (must be done after above)
            % ---------------------------------------------------------
            eventout(tmpind2).duration = lengths(tmpindex)+addlength;
            if eventout(tmpind2).duration == 0, eventout(tmpind2).duration=NaN; end

        end
	end

    if countrm > 0
        fprintf('eeg_insertbound(): event latencies recomputed and %d events removed.\n', countrm);
    end

% look for nested events
% return indices of nested events and
% their total length
% -----------------------------------
function [ indnested, addlen ] = findnested(event, ind)
    indnested = [];
    addlen = 0;
    tmpind = ind+1;

    while tmpind <= length(event) && ...
        event(tmpind).latency < event(ind).latency+event(ind).duration
        if eeg_isboundary(event(tmpind))
            if ~isempty( event(tmpind).duration )
                addlen    = addlen + event(tmpind).duration;
                % otherwise old event duration or merge data discontinuity
            end
        end
        indnested = [ indnested tmpind ];
        tmpind = tmpind+1;
    end

% remove urevent and recompute indices
% THIS FUNCTION IS DEPRECATED
% ------------------------------------
function [event, urevent] = removenested(event, urevent, nestind)

    if ~isempty(nestind)
        fprintf('eeg_insertbound() debug msg: removing %d nested urevents\n', length(nestind));
        nestind = sort(nestind);
        urind = [ event.urevent ]; % this must not be done in the loop
                                   % since the indices are dynamically updated
    end

    for ind = 1:length(nestind)
        % find event urindices higher than the urevent to suppress
        % --------------------------------------------------------
        tmpind = find( urind > nestind(ind) );
        for indevent = tmpind
            event(indevent).urevent = event(indevent).urevent-1;
        end
    end

    urevent(nestind) = [];


function varargout = isoutside(varargin)
%ISOUTSIDE Define avoidance constraint on polytope
%
% F = ISOUTSIDE(P)
%
% Input
%  P : Linear inequalities defining polytope
%
% Since the modelling is based on big-M formulations, all
% involved variables should be explicitly bounded.

% Here is the real overloaded ismember
switch class(varargin{1})
    case {'lmi','constraint'}

        P = varargin{1};
        if ~(all(is(P,'linear')) & all(is(P,'elementwise')))
            error('ISOUTSIDE only applicable to linear inequalities')
        end
        varargout{1} = (yalmip('define',mfilename,varargin{:}) == 1);
        varargout{1} = setupMeta(lmi([]), mfilename,varargin{:});

    case 'char'
        varargout{1} = isoutside_internal(varargin{3});
end


function I = gray2rgb(I)

% converts graylevel image I to identical rgb image
% (useful for compatibility with certain algorithms
% which expect 3 color planes)
%
% Do nothing if image is already rgb
%

if size(I,3) == 1
  I(:,:,3) = I;
  I(:,:,2) = I(:,:,3);
end


%ISUNTRAINED Test on untrained mapping
%
%    I = ISUNTRAINED(W)
%    ISUNTRAINED(W)
%
% True if the mapping type of W is 'untrained' (see HELP MAPPINGS).
% If called without an output argument ISUNTRAINED generates
% an error if the mapping type of W is not 'untrained'.

% $Id: isuntrained.m,v 1.1 2009/03/18 16:12:41 duin Exp $

function i = isuntrained(w)

  if iscell(w)
		i = strcmp(w{1}.mapping_type,'untrained');
		for j=2:length(w)
			if strcmp(w{j}.mapping_type,'untrained') ~= i
				error('Cell array of classifiers cannot be partially trained')
			end
		end
	else
		i = strcmp(w.mapping_type,'untrained');
	end

	if (nargout == 0) & (i == 0)
		error([newline '---- Untrained mapping expected ----'])
	end
return


%
%
%
%      <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %
%      <                                                      > %
%      <                    DISCLAIMER:                       > %
%      <                                                      > %
%      <  THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > %
%      <  THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR   > %
%      <                    OFFICIAL USE.                     > %
%      <                                                      > %
%      <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> %
%
%
%

function [read,setup,sensorNames,sensorLocations,sensorOrientations] = readdata(folder,CHAN,TIME,TRIALS);

[setup,sensorIndex,sensorInfo] = readresfile(folder);

if nargin == 1
    CHAN = 'allchans';
    TIME = 'alltimes';
    TRIALS = 'alltrials';
end

[read,sensorNames,sensorLocations,sensorOrientations] = readmegfile(folder,setup,sensorIndex,sensorInfo,CHAN,TIME,TRIALS);

% Use function [read,setup,sensorNames,sensorLocations] = readdata(folder); to read in parts
% or all of data in a dataset. readdata.m will access readresfile.m to read
% in header, gain/offset, and channel information. It will access
% readmegfile.m to read in the data.
% EXAMPLE:
% [read,sensorNames] = readdata('/data/directory/datasetname.ds');
%
% Enter channel/time/trial parameters in on line 5 of readdata.m.
% FOR THE FUNCTION [read] = readmegfile(folder,setup,sensor,gain,'megsens','alltimes','alltrials');
%
% INPUTS---------------------------------------------------------------------
% folder:     In readdata.m, this should remain as 'folder' everywhere in the
%             program. It is in the command line of matlab where you indicate
%             the file and directory of the dataset you wish to view. It will
%             automatically be used in both readresfile.m and readmegfile.m.
%
% setup:      Enter as 'setup'; setup header information acquired by readresfile.m.
%             This input is needed for the program to work.
%
% sensorIndex:     Enter as 'sensorIndex'; sensor information acquired by readresfile.m,
%             such as megsens, othersens, refsens, and eegsens.
%
% sensorInfo:       Emter as 'gain'; gain/offset information acquired by readresfile.m,
%             including proper_gain, io_gain, and channel locations.
%
% CHAN:       ex: [30:35] - an interval of the desired channels to be read.
%             If CHAN = 'eegsens', only eeg channels/sensors will be read.
%             If CHAN = 'megsens', only meg channels/sensors will be read.
%             If CHAN = 'refsens', only reference channels/sensors will be read.
%             If CHAN = 'othersens' only the other channels/sensors will be
%             read.
%
% TIME:       ex. [0 5] - seconds 0 to 5: the desired time interval to be read.
%             If TIME = 'alltimes', the entire duration of the trial(s) will
%             be read (i.e. TIME = [1:setup.duration]).
%
% TRIALS:     If TRIALS = n, the nth trial will be read.
%             If TRIALS = [3,5,8] (for example), trials 3,5, and 8 will be
%             read and read{1} = data for trial three, read{2} = data for
%             trial 5, and read{3} = data for trial 8.
%             If TRIALS = [3:7] (for example), trials 3 through 7 will be
%             read.
%             If TRIALS = 'alltrials', the data for all of the trials will be
%             read (i.e. TRIALS = [1:setup.duration]).
%
% OUTPUTS--------------------------------------------------------------------
% read:   read contains all of the data. ex. type read{1} for it to display the first
%         set of data on the screen.
%
%----------------------------------------------------------------------------
%
% EXAMPLE:
% [read] = readmegfile(folder,setup,sensorIndex,sensorInfo,'megsens',[0 4],'alltrials');


%MAKESHAPEIMAGES  One-line description here, please.
%
%   output = makeShapeImages(input)
%
%   Example
%   makeShapeImages
%
%   See also
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% INRAE - BIA Research Unit - BIBS Platform (Nantes)
% Created: 2021-07-09,    using Matlab 9.8.0.1323502 (R2020a)
% Copyright 2021 INRAE.

% read data
img = imread('cameraman.tif');

% flipH
imgFlip = imFlip(img, 1);
imwrite(imgFlip, 'cameraman_flipH.png', 'png');

% rotate 90
imgRot90 = imRotate90(img);
imwrite(imgRot90, 'cameraman_rot90.png', 'png');

% crop border
imgCropBorder = imCropBorder(img, [20 40 30 50]);
imwrite(imgCropBorder, 'cameraman_cropBorder.png', 'png');

% add border
imgAddBorder = imAddBorder(img, [20 40 30 50]);
imwrite(imgAddBorder, 'cameraman_addBorder.png', 'png');