[Master Index] [Index for Toolbox]

# tess_align_tool

## (Toolbox/tess_align_tool.m in BrainStorm 2.0 (Alpha))

### Function Synopsis

    varargout = tess_align_tool(varargin)

### Help Text

    TESS_ALIGN_TOOL - Application M-file for tess_align_tool.fig
     function varargout = tess_align_tool(varargin)
        FIG = TESS_ALIGN_TOOL launch tess_align_tool GUI.
        TESS_ALIGN_TOOL('callback_name', ...) invoke the named callback.

     This tool is used to align tesselated surfaces with the MEG sensor coordinate system
     IMPORTANT: All input tesselations MUST be in real dimensions in METERS

     All communication between functions is done using the 'data' structure containing the fields:

     CurrentSubjectFolder: The current subject folder
     Files: A list of all tesselation files loaded from the user (full path)
     Filenames: A list of all filenames loaded
     Comment: The comment structure inside the tesselation files
     View: 1 if user views the tesselated surface
           data.View{nFile}(tessNdx), i:#file, j:#tesselation inside the file
     RGB: color of patch
           data.RGB{nFile}{tessNdx) = [R G B];
     Transparency: Transparency of tesselation, between 0 and 1
     patchHandles: handles of ploted patches, 0 if the patch is not ploted
           data.patchHandles{nFile}(tessNdx)
     plotWindow: 1 if plot window has appeared at least once (it maybe closed by the user though)
     plotHandle: handle of plot window (but window may not exist any more)
     NasionPressed: 1 if Nasion btn pressed, 0 otherwise
     LeftEarPressed: 1 if LeftEar btn pressed, 0 otherwise
     RightEarPressed: 1 if RightEar btn pressed, 0 otherwise
     BtnBackground: color of btn, according to bst color scheme
     BtnBackgroundPressed: color of btn, to show it is pressed (during selection of points)
     NasionCoord: 3x1 vector containing the coords of Nasion (in meters)
     LeftEarCoord: -//-
     RightEarCoord: -//-
     NasionMarker: handle of marker point for nasion
     LeftEarMarker: -//-
     RightEarMarker: -//-
     nVertices{nFile}(tessNdx)
     nFaces{nFile}(tessNdx)
     channelFile: full path to the loaded channel file
     channelHandles: handle for the channel ploted

### Cross-Reference Information

This function calls

    bst_color_scheme                   C:\BrainStorm_2001\Toolbox\bst_color_scheme.m
    bst_layout                         C:\BrainStorm_2001\Toolbox\bst_layout.m
    bst_message_window                 C:\BrainStorm_2001\Toolbox\bst_message_window.m
    file_selection_win                 C:\BrainStorm_2001\Toolbox\file_selection_win.m
    phantom_channel_assignment         C:\BrainStorm_2001\Toolbox\phantom_channel_assignment.m
    select3d                           C:\BrainStorm_2001\PublicToolbox\OtherTools\select3d.m
    warp_everything_bst                C:\BrainStorm_2001\Toolbox\warp_everything_bst.m

This function is called by

    subject_editor                     C:\BrainStorm_2001\Toolbox\subject_editor.m

### Listing of function C:\BrainStorm_2001\Toolbox\tess_align_tool.m

    function varargout = tess_align_tool(varargin)
    %TESS_ALIGN_TOOL - Application M-file for tess_align_tool.fig
    % function varargout = tess_align_tool(varargin)
    %    FIG = TESS_ALIGN_TOOL launch tess_align_tool GUI.
    %    TESS_ALIGN_TOOL('callback_name', ...) invoke the named callback.
    %
    % This tool is used to align tesselated surfaces with the MEG sensor coordinate system
    % IMPORTANT: All input tesselations MUST be in real dimensions in METERS
    %
    %
    % All communication between functions is done using the 'data' structure containing the fields:
    %
    % CurrentSubjectFolder: The current subject folder
    % Files: A list of all tesselation files loaded from the user (full path)
    % Filenames: A list of all filenames loaded
    % Comment: The comment structure inside the tesselation files
    % View: 1 if user views the tesselated surface
    %       data.View{nFile}(tessNdx), i:#file, j:#tesselation inside the file
    % RGB: color of patch
    %       data.RGB{nFile}{tessNdx) = [R G B];
    % Transparency: Transparency of tesselation, between 0 and 1
    % patchHandles: handles of ploted patches, 0 if the patch is not ploted
    %       data.patchHandles{nFile}(tessNdx)
    % plotWindow: 1 if plot window has appeared at least once (it maybe closed by the user though)
    % plotHandle: handle of plot window (but window may not exist any more)
    % NasionPressed: 1 if Nasion btn pressed, 0 otherwise
    % LeftEarPressed: 1 if LeftEar btn pressed, 0 otherwise
    % RightEarPressed: 1 if RightEar btn pressed, 0 otherwise
    % BtnBackground: color of btn, according to bst color scheme
    % BtnBackgroundPressed: color of btn, to show it is pressed (during selection of points)
    % NasionCoord: 3x1 vector containing the coords of Nasion (in meters)
    % LeftEarCoord: -//-
    % RightEarCoord: -//-
    % NasionMarker: handle of marker point for nasion
    % LeftEarMarker: -//-
    % RightEarMarker: -//-
    % nVertices{nFile}(tessNdx)
    % nFaces{nFile}(tessNdx)
    % channelFile: full path to the loaded channel file
    % channelHandles: handle for the channel ploted

    %<autobegin> ---------------------- 02-Nov-2004 16:16:33 -----------------------
    % --------- Automatically Generated Comments Block Using AUTO_COMMENTS ---------
    %
    % CATEGORY: GUI and Related
    %
    % Alphabetical list of external functions (non-Matlab):
    %   publictoolbox\othertools\select3d.m
    %   toolbox\bst_color_scheme.m
    %   toolbox\bst_layout.m
    %   toolbox\bst_message_window.m
    %   toolbox\file_selection_win.m
    %   toolbox\phantom_channel_assignment.m
    %   toolbox\warp_everything_bst.m
    %
    % Subfunctions in this file, in order of occurrence in file:
    %   varargout = initialize_gui(h,eventdata,handles,varargin);
    %   varargout = Load_Callback(h, eventdata, handles, varargin)
    %   varargout = popupmenu1_Callback(h, eventdata, handles, varargin)
    %   varargout = tess_listbox_Callback(h, eventdata, handles, varargin)
    %   varargout = View_Callback(h, eventdata, handles, varargin)
    %   varargout = transp_slider_Callback(h, eventdata, handles, varargin)
    %   varargout = transp_edit_Callback(h, eventdata, handles, varargin)
    %   varargout = editRed_Callback(h, eventdata, handles, varargin)
    %   varargout = editGreen_Callback(h, eventdata, handles, varargin)
    %   varargout = editBlue_Callback(h, eventdata, handles, varargin)
    %   varargout = Nasion_Callback(h, eventdata, handles, varargin)
    %   varargout = NasionClick_Callback
    %   varargout = LeftEar_Callback(h, eventdata, handles, varargin)
    %   varargout = LeftEarClick_Callback
    %   varargout = RightEar_Callback(h, eventdata, handles, varargin)
    %   varargout = RightEarClick_Callback
    %   varargout = CTF_Callback(h, eventdata, handles, varargin)
    %   varargout = Neuromag_Callback(h, eventdata, handles, varargin)
    %   varargout = Align_Callback(h, eventdata, handles, varargin)
    %   varargout = Channels_Callback(h, eventdata, handles, varargin)
    %   varargout = ViewChannels_Callback(h, eventdata, handles, varargin)
    %   varargout = AlignChannels_Callback(h, eventdata, handles, varargin)
    %   phantom_Callback(h, eventdata, handles)
    %   varargout = Quit_Callback(h, eventdata, handles, varargin)
    %
    % Group : Preference data and their calls in this file:
    %   BST = getpref('BrainStorm');
    %
    % Application data and their calls in this file:
    %   'LeftEarMarker'
    %   'NasionMarker'
    %   'RightEarMarker'
    %   'TileType'
    %   'data'
    %   'tess_align_tool_handles'
    %
    %   setappdata(0,'LeftEarMarker',LeftEarMarker);
    %   setappdata(0,'NasionMarker',NasionMarker);
    %   setappdata(0,'RightEarMarker',RightEarMarker);
    %   setappdata(0,'tess_align_tool_handles',handles);
    %   setappdata(data.plotHandle,'TileType','T')
    %   setappdata(fig,'TileType','T')
    %   setappdata(fig,'data',data);
    %
    %   LeftEarMarker = getappdata(0,'LeftEarMarker');
    %   NasionMarker = getappdata(0,'NasionMarker');
    %   RightEarMarker = getappdata(0,'RightEarMarker');
    %   data = getappdata(fig,'data');
    %   handles = getappdata(0,'tess_align_tool_handles');
    %
    % Figure Files opened by this function:
    %   mfilename
    %
    %   Format of strings below: Type:Style:Tag, "String", CallBack Type and Call
    %   <automatic> callback is <Tag>_Callback by Matlab default
    %
    % Callbacks by figure tess_align_tool.fig
    %   uicontrol:checkbox:View "View" uses Callback for <automatic>
    %   uicontrol:checkbox:ViewChannels "View" uses Callback for <automatic>
    %   uicontrol:edit:editBlue "240" uses Callback for <automatic>
    %   uicontrol:edit:editGreen "240" uses Callback for <automatic>
    %   uicontrol:edit:editRed "240" uses Callback for <automatic>
    %   uicontrol:edit:transp_edit "1" uses Callback for <automatic>
    %   uicontrol:listbox:tess_listbox "No Selected Tessellation File" uses Callback for <automatic>
    %   uicontrol:popupmenu:popupmenu1 "No Tessellations Loaded" uses Callback for <automatic>
    %   uicontrol:pushbutton:Align "Align Tessellations" uses Callback for <automatic>
    %   uicontrol:pushbutton:AlignChannels "Align Channels" uses Callback for <automatic>
    %   uicontrol:pushbutton:Channels "Load Channels" uses Callback for <automatic>
    %   uicontrol:pushbutton:LeftEar "Left Pre-auricular" uses Callback for <automatic>
    %   uicontrol:pushbutton:Load "Load" uses Callback for <automatic>
    %   uicontrol:pushbutton:Nasion "Nasion" uses Callback for <automatic>
    %   uicontrol:pushbutton:phantom "Phantom Study" uses Callback for <automatic>
    %   uicontrol:pushbutton:Quit "Quit" uses Callback for <automatic>
    %   uicontrol:pushbutton:RightEar "Right Pre-auricular" uses Callback for <automatic>
    %   uicontrol:radiobutton:CTF "CTF" uses Callback for <automatic>
    %   uicontrol:radiobutton:Neuromag "Neuromag" uses Callback for <automatic>
    %   uicontrol:slider:transp_slider "" uses Callback for <automatic>
    %
    % At Check-in: $Author: Mosher $  $Revision: 22 $  $Date: 11/02/04 2:38p $
    %
    % This software is part of BrainStorm Toolbox Version 2.0 (Alpha) 02-Nov-2004
    %
    % Principal Investigators and Developers:
    % ** Richard M. Leahy, PhD, Signal & Image Processing Institute,
    %    University of Southern California, Los Angeles, CA
    % ** John C. Mosher, PhD, Biophysics Group,
    %    Los Alamos National Laboratory, Los Alamos, NM
    % ** Sylvain Baillet, PhD, Cognitive Neuroscience & Brain Imaging Laboratory,
    %    CNRS, Hopital de la Salpetriere, Paris, France
    %
    % See BrainStorm website at http://neuroimage.usc.edu for further information.
    %
    % Copyright (c) 2004 BrainStorm by the University of Southern California
    % This software distributed  under the terms of the GNU General Public License
    % as published by the Free Software Foundation. Further details on the GPL
    % 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.
    %<autoend> ------------------------ 02-Nov-2004 16:16:33 -----------------------

    % /---Script Author--------------------------------------\
    % |                                                      |
    % | *** Dimitrios Pantazis, Ph.D. student                |
    % | University of Southern California                    |
    % |                                                      |
    % \------------------------------------------------------/

    % Date of creation: May 2004
    % ----------------------------- Script History ---------------------------------
    % 14-May-2004 DP  Creation
    % 16-May-2004 JCM Commenting
    % 17-May-2004 DP  More corrections, additions.
    % 18-May-2004 DP  Minor bug fixes to remove error messages. Aligned files have updated Comments
    %                 Now we can load EEG channels as well
    % 20-May-2004 DP  Add color, change cursor into cross, fix some bugs, change window into 2x2-1
    % 21-May-2004 DP  Display number of vertices/faces
    % 26-May-2004 DP  Align EEG channels by choosing 3 sensors as fiducials
    % 04-June-2004 DP When user chooses color outside [0 255] it reverts to previous color
    %                 Fixed bug: when user choosed Neuromage and aligned, the file was saved with CTF tag
    % 16-June-2004 JCM find fiducial points, changed to NameList = {Channel.Name};,
    %                  (not Channel.Type)
    % 27-Sept-2004 DP Support for Landmark Structure inside the channel file.
    %                 Alignment of channels is done using these landmarks if they exist
    %                 Also, channels are plotted as yellow circles
    % 04-Oct-2004  DP Support for EEG phantom study
    % 13-Oct-2004  DP Remove a command that suppresses warnings
    % ----------------------------- Script History ---------------------------------

    % Last Modified by GUIDE v2.5 04-Oct-2004 11:24:10

    if nargin == 2  % LAUNCH GUI

        fig = openfig(mfilename,'reuse');

        bst_color_scheme(fig);
        setappdata(fig,'TileType','T')
        bst_layout('align',fig,2,1,2)
        set(fig,'visible','on'); % .fig saved as invisible until ready

        % Generate a structure of handles to pass to callbacks, and store it.
        handles = guihandles(fig);
        guidata(fig, handles);

        if nargout > 0
            varargout{1} = fig;
        end

        %the current subject folder is the second argument
        data.CurrentSubjectFolder = varargin{2};
        data.plotWindow = 0;
        data.NasionPressed = 0;
        data.LeftEarPressed = 0;
        data.RightEarPressed = 0;
        data.BtnBackground = get(handles.Load,'BackgroundColor'); %to restore buttons when unpressed
        data.BtnBackgroundPressed = [.7 .7 .3]; %to restore buttons when unpressed

        %save application data
        setappdata(fig,'data',data);

    elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

        try
            if (nargout)
                [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
            else
                feval(varargin{:}); % FEVAL switchyard
            end
        catch
            disp(lasterr);
        end

    end

    % ------------------- Local Functions --------------------------
    % ---------------------------------------------------------------
    function varargout = initialize_gui(h,eventdata,handles,varargin);
    % This function initializes GUI controls, as well as two structures, 'data' and 'changed'

    fig = handles.tess_align_tool; % make sure we have the handle
    handles = guidata(fig);

    % -------------------- CALLBACKS ---------------------------------
    % --------------------------------------------------------------------

    % --------------------------------------------------------------------
    function varargout = Load_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %Open window to ask for tesselation files
    filetype{1} = 'tess';
    [Files Filenames] = file_selection_win(filetype,data.CurrentSubjectFolder);
    data.Files = Files;
    data.Filenames = Filenames;

    if(isempty(Files{1})) %if no files are loaded
        return
    end

    %Get comments from files (to show in listbox)
    for i = 1:size(Files,2)
        temp = load(Files{i},'Comment','Faces','Vertices'); %temp.Comment has the result
        data.Comment{i} = temp.Comment; %data.Comment{i}[j]
        for j = 1:size(data.Comment{i},2) %for all tessellations inside the file
            data.nVertices{i}(j) = size(temp.Vertices{j},2);
            data.nFaces{i}(j) = size(temp.Faces{j},1);
        end
        clear temp
    end

    %update popupmenu
    if ~isempty(Filenames)
        set(handles.popupmenu1,'String',Filenames,'Max',length(Filenames),'enable','on','value',1)
    else
        ErrorString = sprintf('No Tess files were found in %s',data.CurrentSubjectFolder);
        set(handles.listbox,'String',ErrorString)
        return
    end

    %update listbox
    set(handles.tess_listbox,'String',data.Comment{1},'value',1,'enable','on');

    %update other menus and variables
    for i = 1:size(Files,2)
        data.View{i} = zeros(size(data.Comment{i},2),1); %default not view (memory and speed considerations)
        data.Transparency{i} = ones(size(data.Comment{i},2),1); %by default no transparency
        data.patchHandles{i} = zeros(size(data.Comment{i},2),1); %default zero, ie no patch is currently ploted
        for j = 1:size(data.Comment{i},2) %number tessellations inside the file
            data.RGB{i}{j} = [240 240 240];
        end
    end
    set(handles.tessEdit,'string',[num2str(data.nFaces{1}(1)) ' Faces - ' num2str(data.nVertices{1}(1)) ' Vertices ']);
    set(handles.View,'enable','on','value',0);
    set(handles.transp_slider,'value',1,'enable','on');
    set(handles.transp_edit,'string',1,'enable','on');
    set(handles.editRed,'enable','on');
    set(handles.editGreen,'enable','on');
    set(handles.editBlue,'enable','on');

    data.NasionPressed = 0;
    data.LeftEarPressed = 0;
    data.RightEarPressed = 0;
    figure(handles.tess_align_tool);
    setappdata(fig,'data',data);

    %if plot window exists, delete it
    if data.plotWindow & isfield(data,'plotHandle')
        if(ishandle(data.plotHandle))
            delete(data.plotWindow)
        end
    end
    set(handles.ViewChannels,'value',0);

    % --------------------------------------------------------------------
    function varargout = popupmenu1_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %get selected tesselation
    tessNdx = get(handles.popupmenu1,'value');

    %update listbox
    set(handles.tess_listbox,'String',data.Comment{tessNdx},'value',1,'enable','on');

    %update controls
    set(handles.View,'value',data.View{tessNdx}(1));
    set(handles.transp_slider,'value',data.Transparency{tessNdx}(1));
    set(handles.transp_edit,'String',data.Transparency{tessNdx}(1));
    set(handles.editRed,'String',data.RGB{tessNdx}{1}(1));
    set(handles.editGreen,'String',data.RGB{tessNdx}{1}(2));
    set(handles.editBlue,'String',data.RGB{tessNdx}{1}(3));
    set(handles.tessEdit,'string',[num2str(data.nFaces{tessNdx}(1)) ' Faces - ' num2str(data.nVertices{tessNdx}(1)) ' Vertices ']);

    % --------------------------------------------------------------------
    function varargout = tess_listbox_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %get selected tesselation
    tessNdx = get(handles.popupmenu1,'value');
    tessSubNdx = get(handles.tess_listbox,'value');

    %update controls
    set(handles.View,'value',data.View{tessNdx}(tessSubNdx));
    set(handles.transp_slider,'value',data.Transparency{tessNdx}(tessSubNdx));
    set(handles.transp_edit,'String',data.Transparency{tessNdx}(tessSubNdx));
    set(handles.editRed,'String',data.RGB{tessNdx}{tessSubNdx}(1));
    set(handles.editGreen,'String',data.RGB{tessNdx}{tessSubNdx}(2));
    set(handles.editBlue,'String',data.RGB{tessNdx}{tessSubNdx}(3));
    set(handles.tessEdit,'string',[num2str(data.nFaces{tessNdx}(tessSubNdx)) ' Faces - ' num2str(data.nVertices{tessNdx}(tessSubNdx)) ' Vertices ']);

    % --------------------------------------------------------------------
    function varargout = View_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %get current state of controls
    viewmode = get(handles.View,'value'); %1 if checked
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    %update view
    data.View{tessNdx}(tessSubNdx) = viewmode;

    %if plot for the first time (or user closed plot window)
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )

        %open figure to plot
        data.plotHandle = figure('visible','off');
        bst_color_scheme(data.plotHandle);
        setappdata(data.plotHandle,'TileType','T')
        set(data.plotHandle,'menubar','figure','toolbar','figure');
        bst_layout('align',data.plotHandle,2,2,1);
        figure(data.plotHandle); % make active figure
        set(data.plotHandle,'name','Tessellations');
        set(data.plotHandle,'visible','on');
        light
        axis equal
        axis off
        axis vis3d

        %go through all tesselations and see if they need to be ploted
        %this is necessary only if figure was accidentaly closed
        for i = 1:size(data.Comment,2) %for all files

            loadfile = 0; %to avoid loading the same file many times
            for j = 1:size(data.Comment{i},2) %for all tesselations inside the file
                if (data.View{i}(j)) %if asked to plot
                    if(loadfile == 0) %load file if nesessary
                        load(data.Files{i},'Vertices','Faces');
                    end
                    FV.vertices = Vertices{j}';
                    FV.faces = Faces{j};
                    nVertices = size(FV.vertices,1);
                    figure(data.plotHandle);
                    FaceVertexCData = ones(nVertices,1)*data.RGB{i}{j}/255;
                    data.patchHandles{i}(j) = patch(FV,'FaceColor','interp','EdgeColor','none','FaceVertexCData',FaceVertexCData,'faceAlpha',data.Transparency{i}(j)); %plot surface
                    lighting gouraud
                    loadfile = 1;
                end
            end
            loadfile = 0;

        end

        data.plotWindow = 1;
        setappdata(fig,'data',data);
        return
    end

    if(~viewmode) %if asked to stop viewing a surface
        setappdata(fig,'data',data);

        %if patch exists
        h = data.patchHandles{tessNdx}(tessSubNdx);
        if ( h~=0 & ishandle(h) )
            delete(h);
            data.patchHandles{tessNdx}(tessSubNdx)=0;
        end
        setappdata(fig,'data',data);
        return;
    end

    %This part runs only if plot on the same figure again
    load(data.Files{tessNdx},'Vertices','Faces');
    FV.vertices = Vertices{tessSubNdx}';
    FV.faces = Faces{tessSubNdx};
    nVertices = size(FV.vertices,1);
    figure(data.plotHandle);
    FaceVertexCData = ones(nVertices,1)*data.RGB{tessNdx}{tessSubNdx}/255;
    data.patchHandles{tessNdx}(tessSubNdx) = patch(FV,'FaceColor','interp','EdgeColor','none','FaceVertexCData',FaceVertexCData,'faceAlpha',data.Transparency{tessNdx}(tessSubNdx)); %plot surface
    lighting gouraud

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = transp_slider_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    % Get the new value for the threshold from the slider
    NewVal = get(h,'Value');

    % Set the value of the edit box to the new value set by slider
    set(handles.transp_edit,'String',NewVal);

    %update data
    data.Transparency{tessNdx}(tessSubNdx) = NewVal;

    %update patch if available
    h = data.patchHandles{tessNdx}(tessSubNdx);
    if( h~=0 & ishandle(h))
        set(h,'faceAlpha',data.Transparency{tessNdx}(tessSubNdx));
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = transp_edit_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    % Get the new value for the threshold
    NewStrVal = get(h,'String');
    NewVal = str2num(NewStrVal);

    % Check that the entered value falls within the allowable range
    if  isempty(NewVal) | (NewVal< 0) | (NewVal>1),
        % Revert to last value, as indicated by Threshold Slider
        OldVal = get(handles.transp_edit,'Value');
        set(h,'String',OldVal);
    else
        % Set the value of the threshold to the new value
        set(handles.transp_slider,'Value',NewVal);
        data.Transparency{tessNdx}(tessSubNdx) = NewVal;
        %update patch if available
        h = data.patchHandles{tessNdx}(tessSubNdx);
        if( h~=0 & ishandle(h))
            set(h,'faceAlpha',data.Transparency{tessNdx}(tessSubNdx));
        end
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = editRed_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    % Get the new value for the threshold
    NewStrVal = get(h,'String');
    NewVal = str2num(NewStrVal);

    % Check that the entered value falls within the allowable range
    if  isempty(NewVal) | (NewVal< 0) | (NewVal>256),
        % Revert to previous value
        set(h,'String',data.RGB{tessNdx}{tessSubNdx}(1));
    else
        % Set the value of the threshold to the new value
        NewVal = round(NewVal);
        set(h,'string',num2str(NewVal));
        data.RGB{tessNdx}{tessSubNdx}(1) = NewVal;
        %update patch if available
        h = data.patchHandles{tessNdx}(tessSubNdx);
        if( h~=0 & ishandle(h))
            nVertices = size(get(h,'FaceVertexCData'),1);
            FaceVertexCData = ones(nVertices,1)*data.RGB{tessNdx}{tessSubNdx}/255;
            set(h,'FaceVertexCData',FaceVertexCData);
        end
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = editGreen_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    % Get the new value for the threshold
    NewStrVal = get(h,'String');
    NewVal = str2num(NewStrVal);

    % Check that the entered value falls within the allowable range
    if  isempty(NewVal) | (NewVal< 0) | (NewVal>256),
        % Revert to previous value
        set(h,'String',data.RGB{tessNdx}{tessSubNdx}(2));
    else
        % Set the value of the threshold to the new value
        NewVal = round(NewVal);
        set(h,'string',num2str(NewVal));
        data.RGB{tessNdx}{tessSubNdx}(2) = NewVal;
        %update patch if available
        h = data.patchHandles{tessNdx}(tessSubNdx);
        if( h~=0 & ishandle(h))
            nVertices = size(get(h,'FaceVertexCData'),1);
            FaceVertexCData = ones(nVertices,1)*data.RGB{tessNdx}{tessSubNdx}/255;
            set(h,'FaceVertexCData',FaceVertexCData);
        end
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = editBlue_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file

    % Get the new value for the threshold
    NewStrVal = get(h,'String');
    NewVal = str2num(NewStrVal);

    % Check that the entered value falls within the allowable range
    if  isempty(NewVal) | (NewVal< 0) | (NewVal>256),
        % Revert to previous value
        set(h,'String',data.RGB{tessNdx}{tessSubNdx}(3));
    else
        % Set the value of the threshold to the new value
        NewVal = round(NewVal);
        set(h,'string',num2str(NewVal));
        data.RGB{tessNdx}{tessSubNdx}(3) = NewVal;
        %update patch if available
        h = data.patchHandles{tessNdx}(tessSubNdx);
        if( h~=0 & ishandle(h))
            nVertices = size(get(h,'FaceVertexCData'),1);
            FaceVertexCData = ones(nVertices,1)*data.RGB{tessNdx}{tessSubNdx}/255;
            set(h,'FaceVertexCData',FaceVertexCData);
        end
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = Nasion_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %if no plotWindow exists
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )
        bst_message_window('append','Please plot a tesselation surface first');
        return
    end

    %if pressed for first time, activate point clinking
    if(data.NasionPressed == 0)

        %update button status
        set(handles.Nasion,'string','Nasion','backgroundColor',data.BtnBackgroundPressed');
        set(handles.LeftEar,'enable','off');
        set(handles.RightEar,'enable','off');
        set(data.plotHandle,'pointer','crosshair');

        %without pause it crashes when another figure is open!
        pause(.1);
        figure(data.plotHandle);

        %save tool handles on root window, so they can be accessed by NasionClick fn
        setappdata(0,'tess_align_tool_handles',handles);

        %save marker on root window

        %check if we already have a nasion marker
        if(~isfield(data,'NasionMarker') | ~ishandle(data.NasionMarker))
            data.NasionMarker = line('marker','o','markerfacecolor','k','erasemode','xor','visible','off');
        end
        NasionMarker = data.NasionMarker;
        setappdata(0,'NasionMarker',NasionMarker);
        %activate pointclicking on plotWindow
        set(data.plotHandle,'windowbuttondownfcn','tess_align_tool(''NasionClick_Callback'')');
        data.NasionPressed = 1; %it is now pressed
        setappdata(fig,'data',data);
        return
    end

    %if pressed for second time:

    %restore buttons
    set(handles.Nasion,'string','Nasion','backgroundColor',data.BtnBackground');
    set(handles.LeftEar,'enable','on');
    set(handles.RightEar,'enable','on');
    data.NasionPressed = 0;

    %stop finding points in plot window
    set(data.plotHandle,'windowbuttondownfcn','');

    set(data.plotHandle,'pointer','arrow');

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = NasionClick_Callback

    handles = getappdata(0,'tess_align_tool_handles'); %access tesselation tool
    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %read the marker from root window
    NasionMarker = getappdata(0,'NasionMarker');

    %get coordinates of point
    [p v vi face facei] = select3d;
    if(isempty(p) & isempty(v)) %if user did not click on a tesselation
        return
    end
    if (isempty(p)) %if uses chooses the same point again
        p=v;
    end

    set(NasionMarker,'visible','on','xdata',p(1),'ydata',p(2),'zdata',p(3));
    coord = sprintf('%-5.2f %-5.2f %-5.2f (mm)',p(1)*1000,p(2)*1000,p(3)*1000);
    set(handles.nasiontext,'string',coord)

    data.NasionCoord = p;

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = LeftEar_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %if no plotWindow exists
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )
        bst_message_window('append','Please plot a tesselation surface first');
        return
    end

    %if pressed for first time, activate point clinking
    if(data.LeftEarPressed == 0)

        %update button status
        set(handles.LeftEar,'string','LeftEar','backgroundColor',data.BtnBackgroundPressed');
        set(handles.Nasion,'enable','off');
        set(handles.RightEar,'enable','off');
        set(data.plotHandle,'pointer','crosshair');

        %without pause it crashes when another figure is open!
        pause(.1);
        figure(data.plotHandle);

        %save tool handles on root window, so they can be accessed by NasionClick fn
        setappdata(0,'tess_align_tool_handles',handles);

        %save marker on root window

        %check if we already have a nasion marker
        if(~isfield(data,'LeftEarMarker') | ~ishandle(data.LeftEarMarker))
            data.LeftEarMarker = line('marker','o','markerfacecolor','k','erasemode','xor','visible','off');
        end
        LeftEarMarker = data.LeftEarMarker;
        setappdata(0,'LeftEarMarker',LeftEarMarker);
        %activate pointclicking on plotWindow
        set(data.plotHandle,'windowbuttondownfcn','tess_align_tool(''LeftEarClick_Callback'')');
        data.LeftEarPressed = 1; %it is now pressed
        setappdata(fig,'data',data);
        return
    end

    %if pressed for second time:

    %restore buttons
    set(handles.LeftEar,'string','LeftEar','backgroundColor',data.BtnBackground');
    set(handles.Nasion,'enable','on');
    set(handles.RightEar,'enable','on');
    data.LeftEarPressed = 0;

    %stop finding points in plot window
    set(data.plotHandle,'windowbuttondownfcn','');

    set(data.plotHandle,'pointer','arrow');

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = LeftEarClick_Callback

    handles = getappdata(0,'tess_align_tool_handles'); %access tesselation tool
    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %read the marker from root window
    LeftEarMarker = getappdata(0,'LeftEarMarker');

    %get coordinates of point
    [p v vi face facei] = select3d;
    if(isempty(p) & isempty(v)) %if user did not click on a tesselation
        return
    end
    if (isempty(p)) %if uses chooses the same point again
        p=v;
    end

    set(LeftEarMarker,'visible','on','xdata',p(1),'ydata',p(2),'zdata',p(3));
    coord = sprintf('%-5.2f %-5.2f %-5.2f (mm)',p(1)*1000,p(2)*1000,p(3)*1000);
    set(handles.lefteartext,'string',coord)

    data.LeftEarCoord = p;

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = RightEar_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %if no plotWindow exists
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )
        bst_message_window('append','Please plot a tesselation surface first');
        return
    end

    %if pressed for first time, activate point clinking
    if(data.RightEarPressed == 0)

        %update button status
        set(handles.RightEar,'string','RightEar','backgroundColor',data.BtnBackgroundPressed');
        set(handles.LeftEar,'enable','off');
        set(handles.Nasion,'enable','off');
        set(data.plotHandle,'pointer','crosshair');

        %without pause it crashes when another figure is open!
        pause(.1);
        figure(data.plotHandle);

        %save tool handles on root window, so they can be accessed by NasionClick fn
        setappdata(0,'tess_align_tool_handles',handles);

        %save marker on root window

        %check if we already have a nasion marker
        if(~isfield(data,'RightEarMarker') | ~ishandle(data.RightEarMarker))
            data.RightEarMarker = line('marker','o','markerfacecolor','k','erasemode','xor','visible','off');
        end
        RightEarMarker = data.RightEarMarker;
        setappdata(0,'RightEarMarker',RightEarMarker);
        %activate pointclicking on plotWindow
        set(data.plotHandle,'windowbuttondownfcn','tess_align_tool(''RightEarClick_Callback'')');
        data.RightEarPressed = 1; %it is now pressed
        setappdata(fig,'data',data);
        return
    end

    %if pressed for second time:

    %restore buttons
    set(handles.RightEar,'string','RightEar','backgroundColor',data.BtnBackground');
    set(handles.LeftEar,'enable','on');
    set(handles.Nasion,'enable','on');
    data.RightEarPressed = 0;

    %stop finding points in plot window
    set(data.plotHandle,'windowbuttondownfcn','');

    set(data.plotHandle,'pointer','arrow');

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = RightEarClick_Callback

    handles = getappdata(0,'tess_align_tool_handles'); %access tesselation tool
    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %read the marker from root window
    RightEarMarker = getappdata(0,'RightEarMarker');

    %get coordinates of point
    [p v vi face facei] = select3d;
    if(isempty(p) & isempty(v)) %if user did not click on a tesselation
        return
    end
    if (isempty(p)) %if uses chooses the same point again
        p=v;
    end

    set(RightEarMarker,'visible','on','xdata',p(1),'ydata',p(2),'zdata',p(3));
    coord = sprintf('%-5.2f %-5.2f %-5.2f (mm)',p(1)*1000,p(2)*1000,p(3)*1000);
    set(handles.righteartext,'string',coord)

    data.RightEarCoord = p;

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = CTF_Callback(h, eventdata, handles, varargin)

    set(handles.Neuromag,'value',0);

    % --------------------------------------------------------------------
    function varargout = Neuromag_Callback(h, eventdata, handles, varargin)

    set(handles.CTF,'value',0);

    % --------------------------------------------------------------------
    function varargout = Align_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %Check if used specified all points
    if(~isfield(data,'NasionCoord') | ~isfield(data,'LeftEarCoord') | ~isfield(data,'RightEarCoord') )
        bst_message_window('append','Please choose Nasion, Left Ear and Right Ear points before continuing');
        return
    end

    %if used did not choose CTF or Neuromag
    if (get(handles.CTF,'value') == 0 & get(handles.Neuromag,'value') == 0)
        bst_message_window('append','Please choose CTF or Neuromag system before aligning tessellations');
        return
    end

    %if already aligned
    if ( findstr(data.Files{1},'alignedCTF') | findstr(data.Files{1},'alignedNeuromag') )
        ButtonName=questdlg('The file(s) already seem aligned. Do you want to align them again ?', ...
            'Warning', ...
            'Yes','No','No');
        if(strcmp(ButtonName,'No'))
            return
        end
    end

    %delete them, the user may want to specify them again
    if(isfield(data,'NasionMarker'))
        data = rmfield(data,'NasionMarker');
    end
    if(isfield(data,'LeftEarMarker'))
        data = rmfield(data,'LeftEarMarker');
    end
    if(isfield(data,'RightEarMarker'))
        data = rmfield(data,'RightEarMarker');
    end

    %if used everything ok
    bst_message_window('append','Generating files with aligned tessellations...');

    %Fiducial coordinates in m
    NAS = data.NasionCoord;
    LPA = data.LeftEarCoord;
    RPA = data.RightEarCoord;

    % Move to SCS
    % Definition:
    % Xscs = R Xmri + T ; Xmri in mm

    %if CTF-------------------
    if ( get(handles.CTF,'value') == 1 )

        Origin = .5*(LPA+RPA); % in m

        vx = (NAS-Origin)/norm((NAS-Origin));
        vz = cross(vx, LPA-RPA); vz = vz/norm(vz);  % Vector normal to the NLR plane, pointing upwards
        vy = cross(vz,vx); vy = vy/norm(vy);

        R = inv([vx,vy,vz]); % Rotation
        T = - R * Origin; % Translation

        alignment = 'CTF';
    end

    %if Neuromag-------------------
    if ( get(handles.Neuromag,'value') == 1 )

        OR = dot(RPA-NAS,RPA-LPA)/dot(RPA-LPA,RPA-LPA) * (RPA-LPA);
        Origin = RPA - OR;
        vx = OR/norm(OR);
        vy = (NAS-Origin)/norm(NAS - Origin);
        vz = cross(vx,vy);

        R = inv([vx,vy,vz]); % Rotation
        T = - R * Origin; % Translation

        alignment = 'Neuromag';
    end

    %Align tesselations in all files
    for i = 1:size(data.Comment,2) %for all files

        load(data.Files{i},'Vertices','Faces');
        clear Comment;
        for j = 1:size(data.Comment{i},2) %for all tesselations inside the file
            %vert_pcs = R*vert + T
            Vertices{j} = [R T] * [Vertices{j} ; ones(1,size(Vertices{j},2))];
            Comment{j} = [data.Comment{i}{j} '_' alignment];
        end
        data.Comment{i} = Comment;
        if ( get(handles.CTF,'value') == 1 )
            data.Files{i} = [data.Files{i}(1:end-4) '_alignedCTF.mat'];
            data.Filenames{i} = [data.Filenames{i}(1:end-4) '_alignedCTF.mat'];
        else
            data.Files{i} = [data.Files{i}(1:end-4) '_alignedNeuromag.mat'];
            data.Filenames{i} = [data.Filenames{i}(1:end-4) '_alignedNeuromag.mat'];
        end
        save(data.Files{i},'Vertices','Faces','Comment');
        bst_message_window('append',['File created: ' data.Files{i}]);

    end

    bst_message_window('append','Tessellations were aligned successfully');

    %loading aligned tesselations------------

    bst_message_window('append','...');
    bst_message_window('append','Loading Aligned Tessellations...');

    %update popupmenu
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    set(handles.popupmenu1,'String',data.Filenames,'Max',length(data.Filenames),'enable','on')

    %if plot window exists, delete it
    if data.plotWindow & isfield(data,'plotHandle')
        if(ishandle(data.plotHandle))
            delete(data.plotWindow)
        end
    end

    setappdata(fig,'data',data);

    View_Callback(h, eventdata, handles, varargin)
    %update listbox
    tessNdx = get(handles.popupmenu1,'value'); %tesselation index
    tessSubNdx = get(handles.tess_listbox,'value'); %tess inside the file
    set(handles.tess_listbox,'String',data.Comment{tessNdx},'value',tessSubNdx,'enable','on');

    bst_message_window('append','Loading done.');

    % --------------------------------------------------------------------
    function varargout = Channels_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %Open window to ask for channel file
    [filename, pathname] = uigetfile('*channel*.*','Load a channel file from a relevant STUDY folder');
    if(filename == 0)
        return
    end
    data.channelFile = [pathname filename];
    load(data.channelFile);
    set(handles.AlignChannels,'enable','on');

    %Get locations of landmarks
    k = 1;
    if exist('Landmark')
        for i = 1:size(Landmark.Loc,2) %for all landmarks
            SensorLoc(:,k) = Landmark.Loc(:,k);
            k=k+1;
        end
    end
    %Get locations of sensors
    for i = 1:size(Channel,2) %for all sensors
        if ~isempty(Channel(i).Loc) & (strcmp(Channel(i).Type,'MEG') | strcmp(Channel(i).Type,'EEG'))
            SensorLoc(:,k) = Channel(i).Loc(:,1);
            k=k+1;
        end
    end
    nSensors = size(SensorLoc,2);

    %if plot for the first time (or user closed plot window)
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )

        %open figure to plot
        data.plotHandle = figure('visible','off');
        bst_color_scheme(data.plotHandle);
        setappdata(data.plotHandle,'TileType','T')
        set(data.plotHandle,'menubar','figure','toolbar','figure');
        bst_layout('align',data.plotHandle,2,2,1);
        set(data.plotHandle,'visible','on');
        set(data.plotHandle,'name','Tessellations');
        light
        axis equal
        axis off
        axis vis3d
    end

    %if old channel is already ploted
    if(isfield(data,'channelHandles') )
        if(ishandle(data.channelHandles))
            delete(data.channelHandles)
        end
    end

    figure(data.plotHandle);
    hold on;
    data.channelHandles = plot3(SensorLoc(1,:),SensorLoc(2,:),SensorLoc(3,:),'ko');
    set(data.channelHandles,'markerfacecolor','yellow');
    data.SensorLoc = SensorLoc;

    set(handles.ViewChannels,'enable','on','value',1);
    set(handles.AlignChannels,'enable','on');
    data.plotWindow = 1;

    setappdata(fig,'data',data);

    %enable phantom button
    set(handles.phantom,'enable','on');

    % --------------------------------------------------------------------
    function varargout = ViewChannels_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %get current state of controls
    viewmode = get(handles.ViewChannels,'value'); %1 if checked

    %if view enabled
    if(viewmode)

        %if plot for the first time (or user closed plot window)
        if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )

            %open figure to plot
            data.plotHandle = figure('visible','off');
            bst_color_scheme(data.plotHandle);
            setappdata(data.plotHandle,'TileType','T')
            set(data.plotHandle,'menubar','figure','toolbar','figure');
            bst_layout('align',data.plotHandle,2,2,1);
            set(data.plotHandle,'visible','on');
            set(data.plotHandle,'name','Tessellations');
            light
            axis vis3d
        end

        figure(data.plotHandle);
        hold on
        data.channelHandles = plot3(data.SensorLoc(1,:),data.SensorLoc(2,:),data.SensorLoc(3,:),'ko');
        set(data.channelHandles,'markerfacecolor','yellow');
        axis equal
        axis off

    else
        if(ishandle(data.channelHandles))
            delete(data.channelHandles)
        end
    end

    setappdata(fig,'data',data);

    % --------------------------------------------------------------------
    function varargout = AlignChannels_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    if(~isfield(data,'channelFile'))
        bst_message_window('append','No channel file loaded...');
    end

    %if no CTF or Neuromag is selected
    if( ( get(handles.CTF,'value') == 0 ) & ( get(handles.Neuromag,'value') == 0 ) )
        bst_message_window('append','Please select CTF or Neuromag before aligning the channels.');
        return;
    end

    bst_message_window('append','Aligning Channels...');

    %load channel file
    load(data.channelFile)
    nChannels = size(Channel,2);

    %find fiducial points
    if exist('Landmark') %If a Landmark structure is available at channel file
        NameList = Landmark.Name;
    else %if no Landmark structure, check the channels for fiducials
        NameList = {Channel.Name};
    end
    %find nasion
    [nasionNdx,ok] = listdlg('PromptString','Select Nasion:',...
        'SelectionMode','single',...
        'ListString',NameList);
    if(~ok)
        bst_message_window('append','Channel alignment canceled by the user.');
        return
    end
    %find left ear
    [leftearNdx,ok] = listdlg('PromptString','Select Left Pre-auricular:',...
        'SelectionMode','single',...
        'ListString',NameList);
    if(~ok)
        bst_message_window('append','Channel alignment canceled by the user.');
        return
    end
    %find right ear
    [rightearNdx,ok] = listdlg('PromptString','Select Right Pre-auricular:',...
        'SelectionMode','single',...
        'ListString',NameList);
    if(~ok)
        bst_message_window('append','Channel alignment canceled by the user.');
        return
    end

    %Fiducial coordinates in m
    if exist('Landmark') %If a Landmark structure is available at channel file
        NAS = Landmark.Loc(:,nasionNdx);
        LPA = Landmark.Loc(:,leftearNdx);
        RPA = Landmark.Loc(:,rightearNdx);
    else
        NAS = Channel(nasionNdx).Loc(:,1);
        LPA = Channel(leftearNdx).Loc(:,1);
        RPA = Channel(rightearNdx).Loc(:,1);
    end

    %if CTF-------------------
    if ( get(handles.CTF,'value') == 1 )

        Origin = .5*(LPA+RPA); % in m

        vx = (NAS-Origin)/norm((NAS-Origin));
        vz = cross(vx, LPA-RPA); vz = vz/norm(vz);  % Vector normal to the NLR plane, pointing upwards
        vy = cross(vz,vx); vy = vy/norm(vy);

        R = inv([vx,vy,vz]); % Rotation
        T = - R * Origin; % Translation

        alignment = 'CTF';
    end

    %if Neuromag-------------------
    if ( get(handles.Neuromag,'value') == 1 )

        OR = dot(RPA-NAS,RPA-LPA)/dot(RPA-LPA,RPA-LPA) * (RPA-LPA);
        Origin = RPA - OR;
        vx = OR/norm(OR);
        vy = (NAS-Origin)/norm(NAS - Origin);
        vz = cross(vx,vy);

        R = inv([vx,vy,vz]); % Rotation
        T = - R * Origin; % Translation

        alignment = 'Neuromag';
    end

    %align channels
    for i = 1:nChannels
        if ~isempty(Channel(i).Loc)
            Channel(i).Loc = R * Channel(i).Loc + T*ones(1,size(Channel(i).Loc,2));
        end
    end
    %align fiducials
    if exist('Landmark') %If a Landmark structure is available at channel file
        for i = 1:size(Landmark.Name,2) %for all fiducials
            Landmark.Loc(:,i) = R * Landmark.Loc(:,i) + T;
        end
    end

    if exist('Landmark') %If a Landmark structure is available at channel file
        save(data.channelFile,'Channel','Landmark');
    else
        save(data.channelFile,'Channel');
    end
    bst_message_window('append','Aligned Channels saved.');
    bst_message_window('append','Use View check box to make sure proper alignment was performed.');

    %update 'data' structure with new channel
    k = 1;
    for i = 1:size(Channel,2) %for all sensors
        if ~isempty(Channel(i).Loc) & (strcmp(Channel(i).Type,'MEG') | strcmp(Channel(i).Type,'EEG'))
            SensorLoc(:,k) = Channel(i).Loc(:,1);
            k=k+1;
        end
    end
    data.SensorLoc = SensorLoc;
    setappdata(fig,'data',data);

    %if previous channel is ploted, delete it
    if ishandle(data.channelHandles)
        delete(data.channelHandles)
    end

    %view new channels
    set(handles.ViewChannels,'value',1);
    ViewChannels_Callback(h, eventdata, handles, varargin);

    % --- Executes on button press in phantom
    function phantom_Callback(h, eventdata, handles)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %Load Channel structure of the current subject
    load(data.channelFile);
    if(~exist('Landmark'))
        Landmark.Loc = [];
        Landmark.Name = [];
    end

    %check if channel structure loaded is MEG or EEG
    for i = 1:size(Channel,2)
        if strcmp(Channel(i).Type,'MEG')
            bst_message_window('append','You have loaded an MEG channel file. Phantom study can only be used with EEG data.');
            return
        end
    end

    %ask if channels already aligned
    reply = questdlg('Is the loaded channel structure already aligned ?');
    if(strcmp(reply,'No'))
        bst_message_window('append','You need to align the channel structure before beginning a phantom study');
        return
    end
    if(strcmp(reply,'Cancel'))
        bst_message_window('append','Phantom study canceled by user');
        return
    end

    %Define Montreal Channel structure
    MontrealLandmarks.Name = {'Nasion' 'Left Ear' 'Right Ear' 'Inion' 'Vertex'};
    MontrealLandmarks.Loc = ...
        [ 0.10434000000000                  0  -0.00063000000000
        0   0.08362000000000                  0
        0  -0.08802000000000                  0
        -0.09573000000000                  0   0.01785000000000
        -0.01165486688092                  0   0.15651869702676]';
    MontrealChannels.Name = {'Pz' 'Cz' 'Fz' 'T4' 'C4' 'C3' 'T3' 'F7' 'Fp1' 'Fp2' ...
        'F8' 'T5' 'O1' 'O2' 'T6' 'F4' 'F3' 'P4' 'P3'};
    MontrealChannels.Loc = ...
        [ -0.05792508326798                  0   0.13009954873992
        0.01779538314226                  0   0.15466091749303
        0.08767449798897                  0   0.11656588167251
        0.00653288804504  -0.08629718738544   0.05677778617344
        0.01607681017220  -0.04789883192913   0.13972467980692
        0.01581340973800   0.04760625938827   0.13743544824075
        0.00585282960606   0.08437947505500   0.05086735079364
        0.06635064237460   0.07261152071121   0.04376571666545
        0.10878654711220   0.02906067377269   0.04002406853314
        0.10792762776112  -0.03072211171739   0.04223059574545
        0.06732589423211  -0.07503869402653   0.04883069377766
        -0.05072450476274   0.07194389107566   0.05392872365086
        -0.09056653875182   0.02690390942979   0.05734772561876
        -0.08874239284172  -0.03208550284436   0.05931666972874
        -0.04994776227688  -0.07387743004978   0.05896934012721
        0.08113484130894  -0.04864156248658   0.09509197227580
        0.08082812488329   0.05090654332294   0.09286040765330
        -0.05540364981173  -0.05125612202637   0.11002586143836
        -0.05594232491233   0.04968295002833   0.10654646412878 ]';

    %open channel window if not already opened:

    %get current state of controls
    set(handles.ViewChannels,'value',1); %set checked

    %if plot for the first time (or user closed plot window)
    if (~data.plotWindow | ~isfield(data,'plotHandle') | ~ishandle(data.plotHandle) )
        %open figure to plot
        data.plotHandle = figure('visible','off');
        bst_color_scheme(data.plotHandle);
        setappdata(data.plotHandle,'TileType','T')
        set(data.plotHandle,'menubar','figure','toolbar','figure');
        bst_layout('align',data.plotHandle,2,2,1);
        set(data.plotHandle,'visible','on');
        set(data.plotHandle,'name','Tessellations');
        light
        axis vis3d
    end
    %if window already open
    figure(data.plotHandle);
    hold on
    if ~ishandle(data.channelHandles)
        data.channelHandles = plot3(data.SensorLoc(1,:),data.SensorLoc(2,:),data.SensorLoc(3,:),'ko');
        set(data.channelHandles,'markerfacecolor','yellow');
        axis equal
        axis off
    end

    setappdata(fig,'data',data);

    %Open window to assign phantom/subject channels
    [assigned_locs] = phantom_channel_assignment(MontrealChannels,MontrealLandmarks,Channel,Landmark);

    %if process canceled
    if isempty(assigned_locs.phantom)
        bst_message_window('append','Phantom study canceled by user');
        return
    end

    %get bst directories
    BST = getpref('BrainStorm');

    %Get phantom files
    surface_file = fullfile(BST.brainstormHomeDir,'Phantom','montreal_subject','montreal_4layer_tess.mat');
    mr_file = fullfile(BST.brainstormHomeDir,'Phantom','montreal_subject','montreal_subjectimage.mat');

    %name new files (surface and mr)
    current_subject = fullfile(BST.UserDataBase(BST.iUserDataBase).SUBJECTS,BST.CurrentData.SubjectFile);
    [pathstr,name,ext,versn] = fileparts(current_subject);
    warpedsurfacefile = strrep(name,'brainstormsubject','warped_4layer_tess.mat');
    warpedsurfacefile = fullfile(pathstr,warpedsurfacefile);
    warpedmrfile = strrep(name,'brainstormsubject','warped_subjectimage.mat');
    warpedmrfile = fullfile(pathstr,warpedmrfile);

    lm_real = assigned_locs.subject';
    lm_phantom = assigned_locs.phantom';
    warp_everything_bst(lm_real, lm_phantom, surface_file, mr_file,warpedsurfacefile,warpedmrfile);

    bst_message_window('append','Files *warped_4layer_tess.mat and warped_subjectimage.mat');
    bst_message_window('append','where successfully created and saved in the current');
    bst_message_window('append','subject directory');

    % --------------------------------------------------------------------
    function varargout = Quit_Callback(h, eventdata, handles, varargin)

    fig = handles.tess_align_tool; % make sure we have the handle
    data = getappdata(fig,'data');

    %if plot window exists, delete it
    if data.plotWindow & isfield(data,'plotHandle')
        if(ishandle(data.plotHandle))
            delete(data.plotWindow)
        end
    end
    delete(handles.tess_align_tool);

Produced by color_mat2html, a customized BrainStorm 2.0 (Alpha) version of mat2html on Tue Nov 2 16:17:59 2004
Cross-Directory links are: ON