Code covered by the BSD License  

Highlights from
Matlab GUI for Polhemus Digitizer(POLGUI)

image thumbnail
from Matlab GUI for Polhemus Digitizer(POLGUI) by Nitin Bangera
MATLAB GUI interface for polhemus FASTTRAKĀ© used to digitize EEG scalp electrode locations.

polgui_ver1_r14(varargin)
function varargout = polgui_ver1_r14(varargin)
% -------------------------------------------------------------------------
% Copyright (C) 2004 , Nitin B. Bangera  (nitinb2@gmail.com)
% POLGUI Ver 1.0 is distributed under the terms of the open-source BSD License,
% See license.txt for more information.

% -------------------------------------------------------------------------
%                   -- POLGUI Ver 1.0 for Matlab R14 -- 
% -------------------------------------------------------------------------
% Matlab Interface for Polhemus Digitizer( Only with one stylus pen )
% Author Nitin B Bangera 
% 
% NOTE : Set Screen Resolution to "1280 by 1024" or higher for GUI to be
% displayed correctly
% 
%  Usage :
%    
% 
%      ------ polgui_ver1_r14, by itself, creates a new POLGUI_VER1_R14 with
%      default settings of 1 receivers (stylus pen)
% 
%      ------ modify line 235 to change EEG Montage 
%      ------ modify line 271 and 273 to set Baud rate euivalent to that on
%      Polhemus (default set to 57600)
%      Baud Rate Settings on switch on back of Polhemus ( 1= UP, 0=Down)
%       Baud rate    SW 1  SW 2   SW 3
%         1200        0      0      0
%         2400        1      0      0
%         4800        0      1      0
%         9600        1      1      0
%         19200       0      0      1
%         38400       1      0      1
%         57600       0      1      1
%         115200      1      1      1
% Important Variables Saved: in file collected_data.mat
% -------------------------------------------------------------------------
% data_orig --> Original Data including the 3 consecutive points collected 
% for each location for averaging and pen movement error detection
% data -> Averaged data
% data_transf -> Data transformed to head co-ordinate frame
% location -> Names of locations digitized
% count -> Total number of digitized points
% M -> Rotation matrix for transformation
% T -> Translation matrix
% -------------------------------------------------------------------------
% Description of global variables and counters in the code 
% 
% needed_loc LOC DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 special_case strmatch_index redigitize additional T M   
% 
% needed_loc  -> chararcter array with the CARDINAL POINT locations
% and EEG montage locations
% LOC-> Set of digitized  locations
% DATA_ORIG -> Original Data before averaging
% DATA -> Data after averaging 3 successive digitizations for each point
% DATA_TRANSF -> Data after co-ordinate transformation
% COUNTER -> Main Counter
% COUNTER1-> Counter which includes count for 3 successive digitization for each point
% Tag for 4 cases for remove button : 
% special_case
% Case 0-> Initial Condition  , Case 1-> counter <=4
% Case 2-> Counter between 4 and length of needed montage 
% Case 3-> Additional Points
% 
% strmatch_index ->  matches current Vaue in the listbox with needed_loc matrix and returns index 
% redigitize -> Tag to check if redigitization is needed Values: 0 or 1
% additional -> Tag to check if digitization of additional points is needed Values: 0 or 1
% T -> Translation Matrix
% M -> Rotation Matrtix
% --------------------------------------------------------------------------
% Steps for head digitization using POLGUI
% 1.Before starting GUI, edit EEG_MONTAGE variable (on line 215 in this m-file) to set required
% montage to be acquired. 
% 
% 2. Start GUI by typing name of this m-file in MATLAB command line (GUI
% mode) e.g. polgui_ver4_r14 
% 
% 
% Follow these steps in GUI by clicking on respective buttons in sequential
% order
% a. Initialise Device: 
% Serial Object created with specific Baud rate. Change this call back to
% change serial port properties
% 
% To digitize position the tip of the Isotrack Stylus at the desired point
% and click on the dialog box within the GUI. The co-ordinates
% displayed are the averages of three sequential readings taken from the
% digitizer. If they differ from each other by more than 2 mm, you are asked
% to digitize the point again.
% 
% b. Get Test Point:
% Secure one test point
% 
% c. Get Cardinal Points in order LA(left Auricular), RA(Right Auricular)
% and Nasion.
% 
% d. Align Frame from device coordinates to head co-ordinate axes determined 
% by the cardinal points
% Head Coordinate system:
% The head coordinate system is defined as folloew: The x axis passes through the 
% preauricular points with positive values on the right, the y-axis will be
% perpendicular to x axis, passing through the nasion and the positive axis 
% pointing towards the nose, and the z axis will be pointed up, perpendicular to xy plane.
% The auricular points are known as anatomical landmarks or cardinal points.
% 
% Principle: 
% When Align Frame is press, the coordinates of the cardinal locations will 
% change to head frame. Notice the z coordinates of all three points are
% zero. The y coordinates of the auricular points are zero with a positive x
% coordinate on the right and a negative on the left auricular point,
% respectively. The nasion has  a zero x coordinate and its y coordinate is
% positive. The auricular points will be almost symmetrically located: their 
% x coordinates are opposite and about of equal magnitude 
% 
% -Procedure for alignment-------------------------------------------------
% a1. Calculate the new origin coordinates o
% Define three vectors a(nasion-la), b1(ra-la) and b2(la-ra)
% Drop projection of a on b1 and b2 to calculatet1 and t2 respectively.
% find ratio in which projection from b1 (point o) divides vector b1
% o=la+t*b1   o=(Ox,Oy,Oz)
% 
% b1. Define the three new coordinate axes ox(normalised ra-o),oy(normalised
% nasion-o),oz(cross(ox,oy))
% 
% c1. First translate orgin by -o
% Define Translation matrix T as follows:
%     | 1   0   0    0|
%     | 0   1   0    0|
% T = | 0   0   1    0|
%     |-Ox -Oy -Oz   0|
% 
% d1. Then Rotate .Define Rotation Matrix M as folows:
% R=[ox;oy;oz]
% R1=inverse(R) or transpose(R)
%    |"  "  "|
%    |"  R1 "|
% M= |"  "  "|
%    |0  0  0|
% 
% e1. Transform points to new co-ordinate axes with center at o and three
% axes ox,oy and oz
% [xnew ynew znew ]=[xold yold zold 1]*T*M;
% -------------------------------------------------------------------------
% e. Get EEG montage points.
% 
% f. Get additional points
% Fot additional points , click the stylus pen for digitization.
% 
% g. Press stop to close the serial device and delete objects from memory.
% -------------------------------------------------------------------------
%  


% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @polgui_ver1_r14_OpeningFcn, ...
                   'gui_OutputFcn',  @polgui_ver1_r14_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 polgui_ver1_r14 is made visible.
function polgui_ver1_r14_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 polgui_ver1_r14 (see VARARGIN)

set(hObject, 'Units', 'pixels');

handles.banner = imread('head.png'); % Read the image file banner.jpg
info = imfinfo('head.png'); % Determine the size of the image file
axes(handles.logo);
image(handles.banner)
set(handles.logo, ...
    'Visible', 'off', ...
    'Units', 'pixels');

% Choose default command line output for polgui_ver1_r14
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes polgui_ver1_r14 wait for user response (see UIRESUME)
% uiwait(handles.figure1);

%--------------------------------------------------------------------------

% --- Outputs from this function are returned to the command line.
function varargout = polgui_ver1_r14_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} = handles.output;

%--------------------------------------------------------------------------
% --- Executes on button press in initialise.
%Sets Baudrate and created serial object
% To change port name and baudrate change int this callback
function initialise_Callback(hObject, eventdata, handles)
% hObject    handle to initialise (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% EEG Montage to be aquired . Pts 2,3 and 4 are cardinal points_pen
% Edit EEG_MONTAGE to change EEG Montage

EEG_MONTAGE=strvcat('Fp1','Fp2','F3','F4','C3','C4','P3',...
    'P4','O1','02','F7','F8','T3','T4','T5','T6','FZ','CZ','PZ','OZ','A1','A2','Ref','PO1',...
    'PO2','CP1','CP2','FTC1','FTC2','TCP1','TCP2','X31','X32','X33');

handles.needed_loc=strvcat('test','LA','RA','NASION',EEG_MONTAGE);

global special_case strmatch_index no_add additional redigitize T M k;
handles.location=[];  % Handles structure for location names
handles.data=[];      % Handles Structure for final DATA 
handles.count=1;      % Handles structure for overall count of points digitized

special_case=0;% Tag for 4 cases for remove button : 
% Case 0-> Initial Condition  , Case 1-> counter <=4
% Case 2-> Counter between 4 and length of needed montage 
% Case 3-> Additional Points

strmatch_index=0;
no_add=0;       
additional=0;   % Tag to get additonal points, Values:0 or 1
redigitize=0;   % Tag to keep track  of redigitization ,Values 0 or 1
k=5;
str1=sprintf('\n\n\nInitialising device \n');
set(handles.points,'String',[]);
set(handles.text1,'String',str1);
set(handles.remove,'Enable','on');
set(handles.get_test,'Enable','on');
set(handles.align,'Enable','off');
set(handles.get_la,'Enable','off');
set(handles.get_ra,'Enable','off');
set(handles.get_nasion,'Enable','off');
set(handles.get_montage,'Enable','off');
set(handles.get_additional,'Enable','off');
set(handles.stop,'Enable','on');
% Create serial object and set baud rate 
tmp_pc=ispc;
if (tmp_pc)
    handles.s=serial('COM1','BaudRate',57600);
else
    handles.s=serial('/dev/ttyS0','BaudRate',57600);
end
%handles.s=serial('COM1','BaudRate',57600);
guidata(hObject,handles);
str_text1=sprintf('\nDEVICE READY \n\n\nRemove : deletes last digitized point');
str_text2=sprintf('\n\nGet Test Point');
set(handles.text2,'String',str_text2);
set(handles.text1,'String',str_text1);
set(handles.initialise,'Enable','off');
set(handles.text_nasion,'String','No Points Digitized');
set(handles.text_la,'String','No Points Digitized');
set(handles.text_ra,'String','No Points Digitized');


%--------------------------------------------------------------------------
% --- Executes on button press in stop.
% Save data in mat file collected_data
function stop_Callback(hObject, eventdata, handles)
% hObject    handle to stop (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.initialise,'Enable','on');
global DATA DATA_ORIG DATA_TRANSF COUNTER1 COUNTER LOC  count T M redigitize;

data_orig=DATA_ORIG;
data=DATA;
data_transf=DATA_TRANSF;
count=COUNTER-1;
location=LOC;
COUNTER1=[];
COUNTER=[];
DATA_ORIG=[];
DATA=[];
DATA_TRANSF=[];
LOC=[];
save collected_data data_orig data data_transf count location T M;
hold(handles.coordinates,'off');
fclose(handles.s);
delete(handles.s);
clear handles.s;
clear handles.data;
clear handles.location;
clear handles.T; 
clear handles.M;
guidata(hObject,handles);
str3=sprintf('\n\n\nPOLGUI Ver 1.0');
str4=sprintf('\n\n\nPoints Digitized\n\nPress "Initialise" to Start');
set(handles.text1,'String',str3);
set(handles.text2,'String',str4);
set(handles.remove,'Enable','off');
set(handles.stop,'Enable','off');
set(handles.remove,'Enable','on');
set(handles.get_test,'Enable','on');
set(handles.align,'Enable','on');
set(handles.get_la,'Enable','on');
set(handles.get_ra,'Enable','on');
set(handles.get_nasion,'Enable','on');
set(handles.get_montage,'Enable','on');
set(handles.get_additional,'Enable','on');
clear data data_orig data_transf count location T M;


%--------------------------------------------------------------------------
% --- Executes on button press in get_test.
% Secure test point
function get_test_Callback(hObject, eventdata, handles)
% hObject    handle to get_test (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 T M redigitize;
if isempty(COUNTER) COUNTER=1; end
if isempty(COUNTER1) COUNTER1=1; end

if (strcmp(handles.s.status,'closed'))
    handles.s.BytesAvailableFcnCount=48;
    handles.s.BytesAvailableFcnMode = 'byte';
    handles.s.BytesAvailableFcn = {@bytesavailablegui_callback,handles};
    fopen(handles.s);
end
% This loop send request for three successive digitizations which is
% averaged and checked for pen movement
for i=1:3,
%     i
%     COUNTER1
    fprintf(handles.s,'%s','P');
    pause(0.2);
end

if ~isequal(redigitize,1)
    str_text2=sprintf('\n\n\nGet Cardinal Point LA');
    set(handles.text2,'String',str_text2);
    set(handles.get_la,'Enable','on');
    set(handles.get_test,'Enable','off')
end
guidata(hObject,handles);

%--------------------------------------------------------------------------
% --- Executes on button press in get_la.
% Secure Cardinal Point LA(Left Auricular)
function get_la_Callback(hObject, eventdata, handles)
% hObject    handle to get_la (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 T M redigitize;
% This loop send request for three successive digitizations which is
% averaged and checked for pen movement
for i=1:3,
%     i
%     COUNTER1
    fprintf(handles.s,'%s','P');
    pause(0.2);
end

if ~isequal(redigitize,1)
    str_text2=sprintf('\n\n\nGet Cardinal Point RA');
    set(handles.text2,'String',str_text2);
    set(handles.get_ra,'Enable','on');
    set(handles.get_la,'Enable','off')
end
guidata(hObject,handles);

% --- Executes on button press in get_ra.
% Secure Cardinal Point RA(Right Auriculur)
function get_ra_Callback(hObject, eventdata, handles)
% hObject    handle to get_ra (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 T M redigitize;
% This loop send request for three successive digitizations which is
% averaged and checked for pen movement
for i=1:3,
%     i
%     COUNTER1
    fprintf(handles.s,'%s','P');
    pause(0.2);
end
if ~isequal(redigitize,1)
    str_text2=sprintf('\n\n\nGet Cardinal Point NASION');
    set(handles.text2,'String',str_text2);
    set(handles.get_nasion,'Enable','on');
    set(handles.get_ra,'Enable','off');
end
guidata(hObject,handles);

%--------------------------------------------------------------------------
% --- Executes on button press in get_nasion.
% Secure Cardinal Point Nasion
function get_nasion_Callback(hObject, eventdata, handles)
% hObject    handle to get_nasion (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 T M redigitize;

% This loop send request for three successive digitizations which is
% averaged and checked for pen movement
for i=1:3,
%     i
%     COUNTER1
    fprintf(handles.s,'%s','P');
    pause(0.2);
end
if ~isequal(redigitize,1)
    str_nasion=sprintf('\n\nCARDINAL POINTS OBTAINED\n\nALIGN FRAME TO HEAD CO-ORDINATE SYSTEM');   
    set(handles.text2,'String',str_nasion);
    set(handles.align,'Enable','on');
    set(handles.get_nasion,'Enable','off');
end
guidata(hObject,handles);


%--------------------------------------------------------------------------
% --- Executes on button press in get_montage.
% Secure EEG Montage
function get_montage_Callback(hObject, eventdata, handles)
% hObject    handle to get_montage (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global LOC DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 T M redigitize k str_modal;
set(handles.get_montage,'Enable','off');
set(handles.remove,'Enable','Off');

while k<=length(handles.needed_loc) % Check if loop is within the EEG montage points count
    if isequal(k,5)
            str_modal=sprintf('Get Point %s\nPress ESC to exit',handles.needed_loc(5,:));
            str_text2=sprintf('\n\n\n Get Point %s\n\nPress ESC to exit',handles.needed_loc(5,:));
            set(handles.text2,'String',str_text2);
    end
            
    pos_size = get(handles.figure1,'Position');
    user_response = montage_modaldlg_r14('Title','Digitize','String',str_modal);
        switch user_response 
            case 'OK'    % Digitize Point
               for i=1:3,
%                i
%                COUNTER1
               fprintf(handles.s,'%s','P');
               pause(0.2);
               end
            case 'REMOVE LAST PT'  % Remove Last digitized Point
%                     k
%                     LOC
%                     DATA
%                     DATA_TRANSF
                    k=k-1;
                    resultStr= get(handles.points,'String');
                    resultStr(k) =[];
                    DATA(k,:)=[];
                    DATA_TRANSF(k,:)=[];
                    set(handles.points,'String',resultStr)
                    LOC(k,:)=[];
                    redigitize=1;
                    COUNTER1=COUNTER1-3;
                    COUNTER=COUNTER-1;
            case 'No'
               str_text2=sprintf('\n\nPress STOP to finish digitization\nOR\nGet additional Points');
               set(handles.text2,'String',str_text2);
               set(handles.get_additional,'Enable','Off')
               break;
        end
     pause(0.5);
    k=k+1;
    if (redigitize==1) 
        redigitize
        k=k-1;
        str_text2=sprintf('\n\n\nRedigitize Point %s\n\nPress ESC to exit',handles.needed_loc(k,:));
        str_modal=sprintf('Redigitize Point %s\nPress ESC to exit',handles.needed_loc(k,:));
        set(handles.text2,'String',str_text2);
        redigitize=0;
    elseif ~isequal(k,length(handles.needed_loc)+1)
        str_text2=sprintf('\n\n\nGet Point %s\n\nPress ESC to exit',handles.needed_loc(k,:));
        str_modal=sprintf('Get Point %s\nPress ESC to exit',handles.needed_loc(k,:));
        set(handles.text2,'String',str_text2);
    else
        str_text2=sprintf('\n\n\nGet Additional Points if needed');
        set(handles.text2,'String',str_text2);
    end
    if k==length(handles.needed_loc)+1
        str_modal1=sprintf('EEG Montage Digitized\nPress OK to Continue or \nRemove Last Point?');
        user_response = montage_modaldlg_r14('Title','Digitize','String',str_modal1);
        switch user_response 
            case 'OK'
              str_text2=sprintf('\n\nPress STOP to finish digitization\nOR\nGet additional Points');
              set(handles.text2,'String',str_text2);
              set(handles.get_additional,'Enable','On')
              break;
            case 'REMOVE LAST PT'
                    k
                    LOC
                    DATA
                    DATA_TRANSF
                    k=k-1;
                    resultStr= get(handles.points,'String');
                    resultStr(k) =[];
                    DATA(k,:)=[];
                    DATA_TRANSF(k,:)=[];
                    set(handles.points,'String',resultStr)
                    LOC(k,:)=[];
                    redigitize=1;
                    COUNTER1=COUNTER1-3;
                    COUNTER=COUNTER-1;
                    str_modal=sprintf('Redigitize Point %s\nPress ESC to exit',handles.needed_loc(k,:));
            case 'No'
               str_text2=sprintf('\n\nPress STOP to finish digitization\nOR\nGet additional Points');
               set(handles.text2,'String',str_text2);
               set(handles.get_additional,'Enable','Off')
               break;
        end
    end
end
set(handles.get_additional,'Enable','on');
set(handles.remove,'Enable','On');
guidata(hObject,handles);
% set(handles.get_additional,'Enable','on');
        
%--------------------------------------------------------------------------
% --- Executes on button press in get_additional.
function get_additional_Callback(hObject, eventdata, handles)
% hObject    handle to get_additional (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_ORIG DATA_TRANSF COUNTER COUNTER1 additional T M;
set(handles.get_additional,'Enable','off');
additional=1;
str_additional=sprintf('Press Stylus pen to digitize additional points\n Press OK to continue');
uiwait(msgbox(str_additional,'Get Additional Points','help','modal'));


%--------------------------------------------------------------------------
% --- Executes on button press in align.
% Align from device coordinates to head coordinates
function align_Callback(hObject, eventdata, handles)
% hObject    handle to align (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA DATA_TRANSF COUNTER T M LOC;
handles.data=DATA;
hold(handles.coordinates,'off');
la1=handles.data(2,:);
ra2=handles.data(3,:);
nasion=handles.data(4,:);
% rest=data(5:end,:)
a=nasion-la1;
b1=ra2-la1;
b2=la1-ra2;
c=nasion-ra2;
t1=dot(a,b1)/sqrt(dot(b1,b1));
t2=dot(c,b2)/sqrt(dot(b2,b2));
if t1<0 t1=t1*-1;
end
if t2<0 t2=t2*-1;
end
t=t1/(t1+t2);
o=la1+t*b1;

oy=nasion-o;
ox=ra2-o;
ox=ox/sqrt(dot(ox,ox));
oy=oy/sqrt(dot(oy,oy));
oz=cross(ox,oy);
% oz1=o+2*oz

T=[ 1 0 0 0; 0 1 0 0 ;0 0 1 0;-o 0];
R=[ox;oy;oz];
R1=inv(R);
M=[R1 ;0 0 0]; 
% Transformed points from original points
la=[la1 1]*T*M;
ra=[ra2 1]*T*M;
nasion=[nasion 1]*T*M;
% rest_new=rest_new*T*M;
% set(handles.coordinates,'BOX','on','XGrid','on','Ygrid','on','ZGrid','on','ZLim',[0 15]);
plot3([0 5],[0 0],[0 0],'->','Parent',handles.coordinates)
hold(handles.coordinates,'on');
plot3([0 0],[0 5],[0 0],'->','Parent',handles.coordinates)
% hold(handles.coordinates,'on');
plot3([0 0],[0 0],[0 5],'->','Parent',handles.coordinates)
% hold(handles.coordinates,'on');
plot3([la(1,1) ra(1,1) nasion(1,1)],[la(1,2) ra(1,2) nasion(1,2)],[la(1,3) ra(1,3) nasion(1,3)],'*','Parent',handles.coordinates);
hold(handles.coordinates,'on');
set(handles.coordinates,'BOX','on','XGrid','on','Ygrid','on','ZGrid','on','ZLim',[-2 15]);
xlabel(handles.coordinates,'X','Fontweight','bold');
ylabel(handles.coordinates,'Y','Fontweight','bold');
zlabel(handles.coordinates,'Z','Fontweight','bold');
sprintf('Align\n');
handles.center=o;
set(handles.align,'Enable','off');
set(handles.get_montage,'Enable','on');
str_align=sprintf('\n\n\nGet EEG Montage\n\nGet Point %s',handles.needed_loc(COUNTER,:));
set(handles.text2,'String',str_align);
guidata(hObject,handles);


ResultsStr = get(handles.points,'String');
% ResultsStr
DATA_TRANSF(1:4,:)=[DATA(1,:) 1;DATA(2,:) 1;DATA(3,:) 1;DATA(4,:) 1]*T*M;
 
handles.location=LOC
[r,c]=find(abs(DATA_TRANSF)<1e-5);
     for i=1:length(r)
         for j=1:length(c)
             if (i==j)
                 DATA_TRANSF(r(i),c(i))=0;
             end
         end
     end
     
str_la=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA_TRANSF(2,1),DATA_TRANSF(2,2),DATA_TRANSF(2,3)); 
set(handles.text_la,'String',str_la);
str_ra=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA_TRANSF(3,1),DATA_TRANSF(3,2),DATA_TRANSF(3,3));
set(handles.text_ra,'String',str_ra); 
str_nasion=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA_TRANSF(4,1),DATA_TRANSF(4,2),DATA_TRANSF(4,3));
set(handles.text_nasion,'String',str_nasion);

ResultsStr(1,:)={[handles.location(1,:),'   :   ',num2str(DATA_TRANSF(1,1)),'   ',num2str(DATA_TRANSF(1,2)),'   ',num2str(DATA_TRANSF(1,3))]};
ResultsStr(2,:)={[handles.location(2,:),'   :   ',num2str(DATA_TRANSF(2,1)),'   ',num2str(DATA_TRANSF(2,2)),'   ',num2str(DATA_TRANSF(2,3))]};
ResultsStr(3,:)={[handles.location(3,:),'   :   ',num2str(DATA_TRANSF(3,1)),'   ',num2str(DATA_TRANSF(3,2)),'   ',num2str(DATA_TRANSF(3,3))]};
ResultsStr(4,:)={[handles.location(4,:),'   :   ',num2str(DATA_TRANSF(4,1)),'   ',num2str(DATA_TRANSF(4,2)),'   ',num2str(DATA_TRANSF(4,3))]};
handles.translation=T;
handles.rotation=M;
set(handles.points,'String',ResultsStr);
guidata(hObject,handles);




%--------------------------------------------------------------------------
% % --- Executes on selection change in points.
% function points_Callback(hObject, eventdata, handles)
% % hObject    handle to points (see GCBO)
% % eventdata  reserved - to be defined in a future version of MATLAB
% % handles    structure with handles and user data (see GUIDATA)
% 
% % Hints: contents = get(hObject,'String') returns points contents as cell array
% %        contents{get(hObject,'Value')} returns selected item from points


% --- Executes during object creation, after setting all properties.
function points_CreateFcn(hObject, eventdata, handles)
% hObject    handle to points (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

%--------------------------------------------------------------------------
% --- Executes on button press in remove.
% Removes additional points and last digitized points only
function remove_Callback(hObject, eventdata, handles)
% hObject    handle to remove (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global special_case strmatch_index no_add LOC DATA DATA_TRANSF COUNTER COUNTER1;
currentVal=get(handles.points,'Value');
handles.data=DATA_TRANSF;
handles.location=LOC;
resultStr= get(handles.points,'String');
numResults = size(resultStr,1);
strmatch_index=strmatch(handles.location(currentVal,:),handles.needed_loc,'exact');
if currentVal<numResults 
    uiwait(msgbox('User Can remove only the last digitized point','Error','error','modal'));
else 
    if strmatch(handles.location(currentVal,:),handles.needed_loc,'exact') & (numResults<=4)
        special_case=1;
        str6=sprintf('\n\n\nGET POINT %s',handles.location(currentVal,:));
        set(handles.text2,'String',str6);
        resultStr(currentVal) =[];
        handles.data(currentVal,:)=[];
        handles.location(currentVal,:)=[];
        DATA(currentVal,:)=[];
        LOC(currentVal,:)=[];
        COUNTER1=COUNTER1-3;
        switch strmatch_index
            case 1
                set(handles.get_test,'Enable','on');
            case 2
                set(handles.get_la,'Enable','on');
            case 3
                set(handles.get_ra,'Enable','on');
            case 4
                set(handles.get_nasion,'Enable','on'); 
        end
elseif  strmatch(handles.location(currentVal,:),handles.needed_loc,'exact') & (numResults>4) & (numResults<=length(handles.needed_loc))
    special_case==2;
    set(handles.remove,'Enable','Off');
else
    pos_size = get(handles.figure1,'Position');
    % Call remove_modaldlg_r14 with the argument 'Position'.
        user_response = remove_modaldlg_r14('Title','Redigitize');
        switch user_response
        case {'No'}
             special_case=3;
             resultStr(currentVal) =[];
             handles.data(currentVal,:)=[];
             handles.location(currentVal,:)=[];
             LOC(currentVal,:)=[];
             if isequal(no_add,0) 
                  no_add=1;
             else
                 no_add=no_add+1;
             end


     % take no action
        case 'Yes'
     % 
             str7=sprintf('GET POINT %s',handles.location(currentVal,:));
             set(handles.text2,'String',str7);
             resultStr(currentVal) =[];
             handles.data(currentVal,:)=[];
             handles.location(currentVal,:)=[];
             LOC(currentVal,:)=[];
        end
    end
    COUNTER=COUNTER-1;   
    % % If there are no other entries, disable the Remove and Plot 
    % button
    % and change the list sting to <empty>
    if isequal(numResults,length(currentVal)),
        resultsStr = {'<empty>'};
        currentVal = 1;
        set(handles.remove,'Enable','off')
    end
    % % Ensure that list box Value is valid, then reset Value and String
    currentVal = min(currentVal,size(resultStr,1));
    set(handles.points,'Value',currentVal,'String',resultStr)
    % handles.location
    % LOC
    % handles.count
    % Store the new ResultsData
    guidata(hObject, handles);
end
guidata(hObject,handles);

%--------------------------------------------------------------------------
% --- Executes on button press in plot.
% Plot data on seperate figure 
function plot_Callback(hObject, eventdata, handles)
% hObject    handle to plot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global DATA_TRANSF;
status=get(handles.stop,'Enable');
if isequal(status,'off')
    load collected_data.mat;
    DATA_TRANSF=data_transf;
end 
plotColor = {'b','g','r','c','m','y','k'};

Plotdata_x1=DATA_TRANSF(2:end,1);
Plotdata_y1=DATA_TRANSF(2:end,2);
Plotdata_z1=DATA_TRANSF(2:end,3);

if ~isfield(handles,'PlotFigure') | ~ishandle(handles.PlotFigure),
    handles.PlotFigure = figure('Name','Polhemus Digitizer',...
        'Visible','off','NumberTitle','off',...
        'HandleVisibility','off','IntegerHandle','off');
    handles.PlotAxes = axes('Parent',handles.PlotFigure);
    guidata(hObject, handles)
end
% Plot data
pHandles = plot3(Plotdata_x1,Plotdata_y1,Plotdata_z1,'o','Parent',handles.PlotAxes);
set(handles.PlotAxes,'BOX','on','XGrid','on','YGrid','on','ZGrid','on');
xlabel(handles.PlotAxes,'X','Fontweight','bold','Fontsize',12);
ylabel(handles.PlotAxes,'Y','Fontweight','bold','Fontsize',12);
zlabel(handles.PlotAxes,'Z','Fontweight','bold','Fontsize',12);
clear DATA_TRANSF

% Make the figure visible and bring it forward
figure(handles.PlotFigure)

%--------------------------------------------------------------------------
% Bytesavailable callback executes when the byte count reaches the one
% specified in the handles.s.BytesAvailableFcnCount variable.
function bytesavailablegui_callback(s,bytesavailable,handles)
global DATA DATA_ORIG DATA_TRANSF COUNTER1 COUNTER additional redigitize  ;
global LOC;
global T M;
global special_case strmatch_index no_add ; 
set(handles.points,'Value',1);
data_str=fgetl(s); 
data_num=str2num(data_str); % Obtains data from digitizer when bytes-count 
% reaches the limit specified by BytesAvailableFcnCount
% Format of data obtained for the current settings
% 1 2 3 4 5 6 7
% 1 ->01 Header
% 2 ->X position in cms
% 3-> Y position in cms
% 4-> Z position in cms
% 5-> Azimuth attitude in degrees
% 6-> Elevation attitude in degrees
% 7-> Roll attitude in degrees
% Change for your specific device settings
data_num(1,2:4); % Picks the X,Y,Z data

if isequal(additional,1) & COUNTER>4 % For additional points
    DATA(COUNTER,1:3)=data_num(1,2:4);
    handles.count=COUNTER;
    DATA_TRANSF(COUNTER,1:3)=[data_num(1,2:4) 1]*T*M;
    LOC=strvcat(LOC,num2str(COUNTER));
    handles.data=DATA_TRANSF;
    handles.location=LOC;
    Plotdata_x=handles.data(handles.count,1);
    Plotdata_y=handles.data(handles.count,2);
    Plotdata_z=handles.data(handles.count,3);
    if ~isequal(handles.count,1) 
         plot3(Plotdata_x,Plotdata_y,Plotdata_z,'p','Parent',handles.coordinates);
         set(handles.coordinates,'BOX','on','XGrid','on','Ygrid','on','ZGrid','on');
         hold(handles.coordinates,'on');
         xlabel(handles.coordinates,'X','Fontweight','bold');
         ylabel(handles.coordinates,'Y','Fontweight','bold');
         zlabel(handles.coordinates,'Z','Fontweight','bold');
    end
    ResultsStr = get(handles.points,'String');
    ResultsStr = [ResultsStr;{[handles.location(handles.count,:),'   :    ',...
                num2str(handles.data(handles.count,1)),'   ',num2str(handles.data(handles.count,2)),'   ',num2str(handles.data(handles.count,3))]}];
    set(handles.points,'String',ResultsStr);
    str_text2=sprintf('\n\nPress Stylus Button to digitize additional points \n\n  OR\n\nPress STOP to finish digitization');
    set(handles.text2,'String',str_text2);
    COUNTER=COUNTER+1;
%     handles.data
    hObject=handles.get_additional;
    guidata(hObject,handles);
else 
    DATA_ORIG(COUNTER1,1:3)=data_num(1,2:4);   
    if rem(COUNTER1,3)==0 & COUNTER<=length(handles.needed_loc) 
          if (distance(DATA_ORIG(COUNTER1,:),DATA_ORIG(COUNTER1-1,:))>0.2)|(distance(DATA_ORIG(COUNTER1-1,:),DATA_ORIG(COUNTER1-2,:))>0.2)|(distance(DATA_ORIG(COUNTER1,:),DATA_ORIG(COUNTER1-2,:))>0.2)
            redigitize=1; % For redigitization
            COUNTER1=COUNTER1-3;
            if COUNTER<5 % For test and cardinal points
                errorstring=sprintf('Distance between succesive digitization greater than 2 mm\nRedigitize point %s\nPress OK to continue',handles.needed_loc(COUNTER,:));
                uiwait(msgbox(errorstring,'Error','error','modal'));
                switch COUNTER 
                 case 1
                     set(handles.get_test,'Enable','on');
                     set(handles.get_la,'Enable','off');
                     str_text2=sprintf('\n\n\nGet Test Point');
                     set(handles.text2,'String',str_text2);
                 case 2
                     set(handles.get_la,'Enable','on');
                     set(handles.get_ra,'Enable','off');
                     str_text2=sprintf('\n\n\nGet Cardinal Point LA');
                     set(handles.text2,'String',str_text2);
                 case 3
                     set(handles.get_ra,'Enable','on');
                     set(handles.get_nasion,'Enable','off');
                     str_text2=sprintf('\n\n\nGet Cardinal Point RA');
                     set(handles.text2,'String',str_text2);
                 case 4
                     set(handles.get_nasion,'Enable','on');
                     set(handles.get_montage,'Enable','off');
                     str_text2=sprintf('\n\n\nGet Cardinal Point NASION');
                     set(handles.text2,'String',str_text2);
                end   
                DATA;
            end
        else 
             redigitize=0; % For all EEG Montage points
             DATA(COUNTER,:)=(DATA_ORIG(COUNTER1,:)+DATA_ORIG((COUNTER1 -1),:)+DATA_ORIG((COUNTER1-2),:))/3;
             switch COUNTER
                   case 2
                   str_la=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA(2,1),DATA(2,2),DATA(2,3)); 
                  set(handles.text_la,'String',str_la);
                    case 3
                    str_ra=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA(3,1),DATA(3,2),DATA(3,3));
                    set(handles.text_ra,'String',str_ra); 
                    case 4
                    str_nasion=sprintf('X = %2.3g cm\nY = %2.3g cm\nZ = %2.3g cm',DATA(4,1),DATA(4,2),DATA(4,3));
                    set(handles.text_nasion,'String',str_nasion);
             end
              handles.count=COUNTER;
                if isequal(handles.count,1)
                  if special_case==1
                    LOC=strvcat(LOC,handles.needed_loc(strmatch_index,:));
                    special_case=0;
                  else
                  LOC=strvcat(LOC,handles.needed_loc(COUNTER,:));
                  end
                elseif handles.count<size(handles.needed_loc,1)
                if special_case==1
                LOC=strvcat(LOC,handles.needed_loc(strmatch_index,:));
                special_case=0;
                else 
                LOC=strvcat(LOC,handles.needed_loc(COUNTER,:));
                end
                elseif handles.count==size(handles.needed_loc,1)
                if special_case==1
                LOC=strvcat(LOC,handles.needed_loc(strmatch_index,:));
                special_case=0;
                else 
                LOC=strvcat(LOC,handles.needed_loc(COUNTER,:)); 
                end
                elseif special_case==3
                LOC=strvcat(LOC,num2str(COUNTER+no_add));
                 else
                 LOC=strvcat(LOC,num2str(COUNTER));
                end


                handles.location=LOC;
                handles.data=DATA;
                if COUNTER==length(handles.needed_loc)
                    str_text2=sprintf('\n\nGet Additional Points if needed');
                    set(handles.text2,'String',str_text2);
                end
  
                if handles.count>4
                DATA_TRANSF(COUNTER,1:3)=[data_num(1,2:4) 1]*T*M;
                handles.data=DATA_TRANSF;
                end


                Plotdata_x=handles.data(handles.count,1);
                Plotdata_y=handles.data(handles.count,2);
                Plotdata_z=handles.data(handles.count,3);
                if ~isequal(handles.count,1)
                    plot3(Plotdata_x,Plotdata_y,Plotdata_z,'p','Parent',handles.coordinates);
                    set(handles.coordinates,'BOX','on','XGrid','on','Ygrid','on','ZGrid','on');
                    hold(handles.coordinates,'on');
                    xlabel(handles.coordinates,'X','Fontweight','bold');
                    ylabel(handles.coordinates,'Y','Fontweight','bold');
                    zlabel(handles.coordinates,'Z','Fontweight','bold');
                end


                COUNTER=COUNTER+1;
                ResultsStr = get(handles.points,'String');
                if isequal(handles.count,1)
                ResultsStr = {[handles.location(handles.count,:),'   :   ',num2str(handles.data(1,1)),'   ',num2str(handles.data(1,2)),'   ',num2str(handles.data(1,3))]};
                else
                ResultsStr = [ResultsStr;{[handles.location(handles.count,:),'   :    ',...
                num2str(handles.data(handles.count,1)),'   ',num2str(handles.data(handles.count,2)),'   ',num2str(handles.data(handles.count,3))]}];
                end   
                set(handles.points,'String',ResultsStr);
          end
    end


    COUNTER1=COUNTER1+1;
    handles.count=COUNTER;
    handles.location=LOC;
    hObject=handles.get_montage;
    guidata(hObject,handles);
    LOC
end

%--------------------------------------------------------------------------
% Function to Calculate euclidean distance between digitized points
function d=distance(X,Y)
d=sqrt(sum((X-Y).^2));

%--------------------------------------------------------------------------
% --- Executes during object creation, after setting all properties.
function logo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to logo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: place code in OpeningFcn to populate logo

%--------------------------------------------------------------------------

Contact us at files@mathworks.com