image thumbnail

eogui – a software to analyze electro-oculogram (EOG) recordings

by

 

10 Aug 2011 (Updated )

detects blinks and saccadic eye movements in EOG recordings

eogui.m
function varargout = eogui(varargin)
% eogui - GUI for analyzing electro-oculogram (EOG) data

% Syntax:  varargout = eogui(varargin)
%
% Example call: 
%    eogui
%
% Other m-files required: all included in the zip file 
%
% Author: Maik Hofmann
% email: Maik_hofmann@web.de
% $Id: eogui.m 15 2005-03-10 12:53:40Z maik $
% modified by Robert Schleicher August 2011

%------------- BEGIN CODE -------------- 

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @eogui_OpeningFcn, ...
                   'gui_OutputFcn',  @eogui_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


clc %RS

%------------------------------------
%  load settings, 
%------------------------------------
function loadmainconfig(handles)
if exist('main.config')
    config=load('main.config','-mat');
    
    if(config.stayontop==1)
        set(handles.cOnTop,'Value',get(handles.cOnTop,'Max'));
    else
        set(handles.cOnTop,'Value',get(handles.cOnTop,'Min'));
    end    
    set(handles.mFilteraktiv,'Checked',config.sakkfilter);
    cOnTop_Callback(handles.cOnTop,[], handles);        
end


function savemainconfig(handles)
config.stayontop=get(handles.cOnTop,'Value')==get(handles.cOnTop,'Max');
config.sakkfilter=get(handles.mFilteraktiv,'Checked');
 
save('main.config','-struct','config','-mat');



% --- Executes just before eogui is made visible.
%##########################################################################
function eogui_OpeningFcn(hObject, eventdata, handles, varargin)
set(handles.figure1,'CloseRequestFcn',...
    'eogui(''figure1_CloseRequestFcn'',gcf,[],guidata(gcf))');

addpath(pwd);

%------------------------------------
% Set default parameter.
%------------------------------------
handles.parameter=setupdefaultparameter();
if(isempty(handles.parameter))
    close;
    return;
end

%------------------------------------
% Get raw data file.
%------------------------------------
handles.filename=[];
sakkaden=[];        
blinks=[];
handles.issaved=true;
guidata(hObject, handles);

[filename, pathname, filterindex] = uigetfile( ...
   {'*.mat','EOG-RAW-Data(*.mat)'; ...    
    '*.vhdr','EOG-Brain Vision (*.vhdr)';...	
    '*.dat','EOG-ATISA (*.dat)';...
    '*.vpd','Varioport (*.vpd)';...
    '*.dat','EOG-Knigstein (*.dat)';...
    }, 'Open raw data');

if isequal(filename,0) | isequal(pathname,0)   
   close;
   return;
end;
handles.filename=fullfile(pathname, filename);



isparacomplete=false; %RS: for settings dialogue


%------------------------------------
%  load file
%------------------------------------
switch(filterindex)
    case 1 %load mat file
        eogreader=matreader(handles.filename);
                        
    case 2 %load VHDR
        eogreader=vhdrreader(handles.filename);      
        
    case 3 %load ATISA
        eogreader=atisareader(handles.filename);
        
    case 4 %load VPD
        eogreader=vpdreader(handles.filename); 		
                
    case 5         %load idat
        eogreader=idatreader(handles.filename);
                               
    otherwise                
        close;
        error('Format not possible');
        return;
end;


%------------------------------------
%  restrict area
%------------------------------------
sb=selbereich(1,get(eogreader,'SamplesPerChannel'));
handles.input=[];
if isempty(sb)
    handles.input=read(eogreader);
else    
    handles.input=read(eogreader,sb(1),sb(2)-sb(1)-1);    
end

%RS 3.8.: file & range checks moved here....
if(isempty(handles.input))    
    close;
    error('Files could not be read');
    return;
end 

dim=size(handles.input);
if(dim(2) <3)
    errordlg('Entry format not possible','Error');
    close;
    return;
end

if(dim(1) <6000)
    errordlg('Recording too short','Error');
    close;
    return;
end


disp(['filename: ' filename]);

%------------------------------------
%  select channels
%------------------------------------
%{% 
%RS: 7.8.11
handles.parameter.mapping = [1,2,3,0,0,0];
	handles.parameter.mapping = kanalauswahl(handles.input,handles.parameter.mapping,{'Horizontal','Vertical','Trigger'});
	m = handles.parameter.mapping;
    if isempty(m)
        close;
        return;
    end    
    data = handles.input;
    if size(data,2)<4 %RS: 7.8.11 - if no trigger signal is present
        emptytrigger=zeros(length(data),1);
        data=[data emptytrigger];       
    end   
    % auswahl anwenden
    d1 = data(:,1);
    d2 = data(:,m(1)+1);
    d3 = data(:,m(2)+1);
    d4 = data(:,m(3)+1);
    
    %invertieren
    if m(4)
        d2 = -1 * d2;
    end
    if m(5) 
        d3 = -1 * d3;
    end
    if m(6)
        d4 = -1 * d4;
    end       
    handles.input = [d1,d2,d3,d4,d4]; % braucht 2 Trigger, selektion kann aber aktuell nur einen, darum 2mal d4  
%} %

    %{ 
RS: deactivated, might be confusing
% channel mapping
% handles.input=mappgindlg(handles.input);
handles.parameter.mapping=mappgindlg(handles.input);
m = handles.parameter.mapping;
o = handles.input;
handles.input = [o(:,m(1)),o(:,m(2)),o(:,m(3)),o(:,m(4)),o(:,m(5))];
%}

handles.samplerate=get(eogreader,'SampleRate');

%------------------------------------
%  CALIBRATION: use old parameters OR start new calibration
%------------------------------------

if exist('lastpara.config')==2,    
    b=questdlg({'................Use last settings?   ',' ',' (Press "Cancel" to load Param.dat)'},...
                'Settings','Yes','No','Cancel','No');      
 
    switch b,
        case 'Yes'
            handles.parameter=loadParam('lastpara.config');            
            isparacomplete=true;     
        case 'No' %start Calibration dialogue
            if(~isparacomplete)
                handles.parameter=eichen(handles.input,handles.parameter);
                if(isempty(handles.parameter))
                    warning('Calibration unsuccessful.');
                    close;
                    return;
                end            
            end
        case 'Cancel' % if Knigstein format file is loaded switch to Param.dat dialogue
            if filterindex ~=5
                close;
                return;
            elseif(filterindex==5 && ~isparacomplete)    % RS: filterindex from file selection
                [filename,pathname] = uigetfile({'PARAM*.DAT', ...
                'Knigstein Parameter (PARAM*.DAT)'},'Open PARAM.DAT');    
                if ~isequal(filename,0) && ~isequal(pathname,0)
                    parameter=loadIDATParam(fullfile(pathname, filename),handles.parameter);
                    if(~isempty(parameter))
                        isparacomplete=true;
                        handles.parameter=parameter;
                    end       
                end
            end       
    end %RS: from settings switch
end %RS: from if exist('lastpara.config')==2,

%----------------------------------
% Settings, Stimulus Selection
%----------------------------------
% if isfield(handles.parameter,'kextension')    
%     handles.parameter.kextension=reizauswertung(handles.parameter.kextension,handles.input);
% else
%     handles.parameter.kextension=reizauswertung(handles.input);
% end
% if isempty(handles.parameter.kextension) return; end; % abbruch ?


%----------------------------------
% Show Summary (=zusammenfassung)
%----------------------------------
handles.parameter=zusammenfassung(handles.input,handles.parameter);
if isempty(handles.parameter)    
    close;
    return;
end




%----------------------------------
% Save parameters.
%----------------------------------
saveParam('lastpara.config',handles);


dim=size(handles.input);
if(dim(1) <6000)
    errordlg('Recording too short','Error');
    close;
    return;
end

%load existing filter list
handles.filterlist=[];
if(exist('dfilter.config')==2)  
   data=load('dfilter.config','liste','-mat');    
   handles.filterlist=data.liste;
end
guidata(hObject, handles);

loadmainconfig(handles);




%------------------------------------
%  start analysis, guidata are saved here
%------------------------------------
mDetect_Callback(hObject, eventdata, handles)








%------------------------------------
% Modal, wait till all is done
%------------------------------------
%uiwait(handles.figure1);


%##########################################################################
function parameter=loadParam(fname);
s=load(fname,'-mat');
parameter=s.parameter;
    
%##########################################################################
function parameter=saveParam(fname,handles);
    save(fname,'-struct','handles','parameter','-v6');
    

    
%##########################################################################
function geheZu(handles,zeitpkt)
pos= find(handles.algodata.zeitachse>zeitpkt,1);
if isempty(pos) return; end;

pos=pos-(handles.fensterbreite/2);
if(pos<0) pos=0;end;
ende=pos+handles.fensterbreite;
scount=length(handles.algodata.zeitachse);
if(ende>scount) ende=scount;end;
handles.anzeigebereich=1+pos:ende;
guidata(handles.figure1, handles);
rePaint(handles);




%-- Display all
%##########################################################################
function rePaint(handles)
if(~isfield(handles,'screen')) return; end;
if(length(handles.anzeigebereich)<100) return; end;

% search middle of display area
n=fix(length(handles.anzeigebereich) /2);

% Update text field time 
set(handles.eTime,'String',num2str(handles.algodata.zeitachse(handles.anzeigebereich(n))));

% Update slider
samplecount=length(handles.algodata.zeitachse);
sval=(handles.anzeigebereich(1)-1)/(samplecount-handles.fensterbreite);
if(sval<=get(handles.sPosition,'Max'))
    set(handles.sPosition,'Value',sval);
else
    set(handles.sPosition,'Value',get(handles.sPosition,'Max'));
end


%------------------------------------
%  adjust parameters according to sampling rate
%------------------------------------
parameter=adjustparameters(handles.parameter,handles.samplerate);

%------------------------------------
%  determine height 
%------------------------------------
c1dim=[min(handles.algodata.channel1.sig1(handles.anzeigebereich))-5 ...
    max(handles.algodata.channel1.sig1(handles.anzeigebereich))+5];

if(c1dim(1)+20>c1dim(2))c1dim(2)=c1dim(1)+20; end;


c2dim=[min(handles.algodata.channel2.sig1(handles.anzeigebereich))-5 ...
    max(handles.algodata.channel2.sig1(handles.anzeigebereich))+5];
if(c2dim(1)+20>c2dim(2))c2dim(2)=c2dim(1)+20; end;

c1sdim=[min(handles.algodata.channel1.sig3(handles.anzeigebereich))...
    max(handles.algodata.channel1.sig3(handles.anzeigebereich))];

c2sdim=[min(handles.algodata.channel2.sig3(handles.anzeigebereich))...
    max(handles.algodata.channel2.sig3(handles.anzeigebereich))];

calldim=[handles.algodata.zeitachse(handles.anzeigebereich(1))...
                handles.algodata.zeitachse(handles.anzeigebereich(end))];



axeslist=[handles.screen.x.main handles.screen.x.speed handles.screen.y.main handles.screen.y.speed];        

%----------------------------------------
%  clear all windows
%------------------------------------
for i=1:length(axeslist)
    axes(axeslist(i));
    cla;
end

%----------------------------------------
%  set new dim
%------------------------------------
set(handles.screen.x.main,'ylimmode','manual','ylim',c1dim,'xlimmode','manual','xlim',calldim);
set(handles.screen.y.main,'ylimmode','manual','ylim',c2dim,'xlimmode','manual','xlim',calldim);
set(handles.screen.x.speed,'ylimmode','manual','ylim',c1sdim,'xlimmode','manual','xlim',calldim);
set(handles.screen.y.speed,'ylimmode','manual','ylim',c2sdim,'xlimmode','manual','xlim',calldim);
 

begin_t=handles.algodata.zeitachse(handles.anzeigebereich(1));
end_t=handles.algodata.zeitachse(handles.anzeigebereich(end));


%----------------------------------------
%  draw coarse area
%------------------------------------
c=size(handles.algodata.grobdebug);
for j=1:c(1)    
        rstart=handles.algodata.grobdebug(j,1);
        rende=handles.algodata.grobdebug(j,2);
        %---------------------------------------------
        %1. relevant data are yet to come.
        if(rende<begin_t) continue, end
        %2. are already over.
        if(rstart>end_t) j=inf; break; end            
        %3. need to be cut.
        if(rstart<begin_t)
            rstart=begin_t;
        end
        if(rende>end_t)
            rende=end_t;
        end          
        %---------------------------------------------
    
    for i=1:length(axeslist)
        axes(axeslist(i));
        hold on;    
        dim = get(gca,'ylim');            
        fill([rstart rende rende rstart],[dim(1) dim(1) dim(2) dim(2)],[0.7 0.9 1],'FaceAlpha',0.7);
        hold off;    
    end
end


%----------------------------------------
%  Draw artefacts
%------------------------------------
c=size(handles.algodata.artefakte);
for j=1:c(1)     
        rstart=handles.algodata.artefakte(j,1);
        rende=handles.algodata.artefakte(j,2);
        %---------------------------------------------
        %1. Relevant data are yet to come.
        if(rende<begin_t) continue, end
        %2. Are already over.
        if(rstart>end_t) j=inf; break; end            
        %3. Need to be cut.
        if(rstart<begin_t)
            rstart=begin_t;
        end
        if(rende>end_t)
            rende=end_t;
        end          
        %---------------------------------------------        
    for i=1:length(axeslist)
        axes(axeslist(i));
        hold on;    
        dim = get(gca,'ylim');            
        fill([rstart rende rende rstart],[dim(1) dim(1) dim(2) dim(2)],[1 0.7 0.7],'FaceAlpha',0.8);
        hold off;    
    end
end

%----------------------------------------
% draw stimuli
%------------------------------------
c=size(handles.reiz1);
for j=1:c(1)
    pos=abs(handles.reiz1(j,1));                
    if(pos<begin_t) continue; end    
    if(pos>end_t) break; end     
    for i=1:length(axeslist)
        axes(axeslist(i));    
        hold on;                
        dim = get(gca,'ylim');    
        plot([pos pos],[dim(1) dim(2)],'LineStyle','--','Color', [0.85 0.7 1],'Marker','x');
        hold off;
    end
end

c=size(handles.reiz2);
for j=1:c(1)
    pos=abs(handles.reiz2(j,1));            
    if(pos<begin_t) continue; end    
    if(pos>end_t) break; end     
    
    for i=1:length(axeslist)
        axes(axeslist(i));    
        hold on;      
        dim = get(gca,'ylim'); %RS: von mir am 13.1.eingefgt
        plot([pos pos],[dim(1) dim(2)],'LineStyle','--','Color', [1 0.6 0.78]);
        hold off;
    end
end





%----------------------------------------
% draw saccades
%------------------------------------
color=0.9;
for j=1:length(handles.sakkaden)                

        rstart=handles.sakkaden(j).start;
        rende=handles.sakkaden(j).ende;

        %---------------------------------------------
        %1. Relevant data are yet to come.
        if(rende<begin_t) continue, end
        %2. Are already over.
        if(rstart>end_t) break; end            
        %3. Need to be cut.
        if(rstart<begin_t)
            rstart=begin_t;
        end
        if(rende>end_t)
            rende=end_t;
        end          
        %---------------------------------------------            


        haxes=[];
        if(handles.sakkaden(j).channel==0)                
            haxes=handles.screen.x.main;  
            start_amp=handles.sakkaden(j).startampx;
            stop_amp=handles.sakkaden(j).endeampx;            
        else
            start_amp=handles.sakkaden(j).startampy;
            stop_amp=handles.sakkaden(j).endeampy;            
            haxes=handles.screen.y.main;
        end
        
        if(~isempty(haxes))
            axes(haxes);
            hold on;    
            fill([rstart rende rende rstart],...
                [start_amp start_amp stop_amp stop_amp],[0 1 0],'LineStyle',':','FaceAlpha',0.7);

            % max speed pos
            %------------------------
            dim = get(gca,'ylim');    
            pos=handles.sakkaden(j).qmaxspeedpos;             
            plot([pos pos],[dim(1) dim(2)],':r');
            hold off;              
        end
end

%----------------------------------------
% Draw blinks
%------------------------------------
if(~isempty(handles.screen.y.main))    
color=0.9;    
for j=1:length(handles.blinks)     
    axes(handles.screen.y.main);        % handles.blinks are only in the yplot !
    hold on;    

    rstart=handles.blinks(j).bstart1;
    rende=handles.blinks(j).bende1;
        %---------------------------------------------
        %1. Relevant data are yet to come.
        if(rende<begin_t) continue, end
        %2. Are already over.
        if(rstart>end_t) break; end            
        %3. Need to be cut.
        if(rstart<begin_t)
            rstart=begin_t;
        end
        if(rende>end_t)
            rende=end_t;
        end          
        %---------------------------------------------

    start_amp=handles.blinks(j).bstartamp1;
    stop_amp=handles.blinks(j).bendeamp1;    
    fill([rstart rende rende rstart],[start_amp start_amp stop_amp stop_amp],[1 1 0],'LineStyle',':','FaceAlpha',0.7);


    start_amp=handles.blinks(j).bstartamp2;
    stop_amp=handles.blinks(j).bendeamp2;
    rstart=handles.blinks(j).bstart2;
    rende=handles.blinks(j).bende2;
        %---------------------------------------------
        %1. Relevant data are yet to come.
        if(rende<begin_t) continue, end
        %2. Are already over.
        if(rstart>end_t) break; end            
        %3. Need to be cut.
        if(rstart<begin_t)
            rstart=begin_t;
        end
        if(rende>end_t)
            rende=end_t;
        end          
        %---------------------------------------------        
    fill([rstart rende rende rstart],[start_amp start_amp stop_amp stop_amp],[0.6 0.6 0],'LineStyle',':','FaceAlpha',0.7);

    hold off;    
end
end

%----------------------------------------
% draw X-graph
%------------------------------------
if(~isempty(handles.screen.x.main))
    axes(handles.screen.x.main);
    hold on; 
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...        
                handles.algodata.channel1.sig0(handles.anzeigebereich),'c','LineWidth',2);
            
            % draw step 1       
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...
                handles.algodata.channel1.sig1(handles.anzeigebereich)); 
            
            % draw step 2
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...        
                handles.algodata.channel1.sig2(handles.anzeigebereich),'r');
    hold off;
end

%----------------------------------------
% draw X-speed
%------------------------------------
if(~isempty(handles.screen.x.speed))
    axes(handles.screen.x.speed);
    %cla;
    hold on;    
        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.channel1.sig3(handles.anzeigebereich));
        y=parameter.feinsuche.x.schwellwert;

        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.zeitachse(handles.anzeigebereich)*0+y);        

        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.zeitachse(handles.anzeigebereich)*0-y);        
    hold off
end


%----------------------------------------
% draw Y-graph
%------------------------------------
if(~isempty(handles.screen.y.main))
    axes(handles.screen.y.main);   
    hold on;
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...
                handles.algodata.channel2.sig0(handles.anzeigebereich),'c','LineWidth',2);
            
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...
                handles.algodata.channel2.sig1(handles.anzeigebereich)); % draw step 1 
                            
            plot(handles.algodata.zeitachse(handles.anzeigebereich),...
                handles.algodata.channel2.sig2(handles.anzeigebereich),'r'); % draw step 2                
    hold off;
end

%----------------------------------------
% draw Y-speed
%------------------------------------
if(~isempty(handles.screen.y.speed))
    axes(handles.screen.y.speed);    
    hold on;    
        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.channel2.sig3(handles.anzeigebereich));
        y=parameter.feinsuche.y.schwellwert;
        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.zeitachse(handles.anzeigebereich)*0+y);        
        plot(handles.algodata.zeitachse(handles.anzeigebereich),...
            handles.algodata.zeitachse(handles.anzeigebereich)*0-y);        
    hold off;
end






% --- Outputs from this function are returned to the command line.
%##########################################################################
function varargout = eogui_OutputFcn(hObject, eventdata, handles) 
varargout{1} = [];    



%##########################################################################
function eTime_Callback(hObject, eventdata, handles)
pos=str2double(get(hObject,'String'));
if(isnan(pos))
    %MesseageBox !!!
    return;
end
geheZu(handles,pos);


    
%##########################################################################
function eTime_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end




%##########################################################################
function sPosition_Callback(hObject, eventdata, handles)
samplecount=length(handles.algodata.zeitachse);
v2=fix(get(hObject,'Value')* (samplecount-handles.fensterbreite) );
handles.anzeigebereich=1+v2:v2+handles.fensterbreite;
guidata(handles.figure1, handles);
rePaint(handles);



%##########################################################################
function sPosition_CreateFcn(hObject, eventdata, handles)
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


%##########################################################################
function lbSakkaden_Callback(hObject, eventdata, handles)
if(isempty(handles.sakkaden))
    return;
end
index=get(hObject,'Value');
sakkade=handles.sakkaden(index);
if( strcmp(get(gcf,'SelectionType'),'open'))
    %hier wurde 2 mal geklickt
    geheZu(handles,sakkade.start);
else
    amp=sqrt((sakkade.endeampx-sakkade.startampx)^2 + (sakkade.endeampy-sakkade.startampy)^2);
    time=(sakkade.ende-sakkade.start)/1000; % time in s    
    speed=amp/time;

    
    %clicked 1 time
    set(handles.eEvent,'String',...
        {'Type: Saccade';
        ['Channel: ' num2str(sakkade.channel)] ;
        ['Start: ' num2str(sakkade.start)];
        ['End: ' num2str(sakkade.ende)];
        ['AmpX: ' num2str(sakkade.ampx)];                
        ['StartAmpX: ' num2str(sakkade.startampx)];        
        ['EndAmpX: ' num2str(sakkade.endeampx)];                
        ['AmpY: ' num2str(sakkade.ampy)];                        
        ['StartAmpY: ' num2str(sakkade.startampy)];        
        ['EndAmpY: ' num2str(sakkade.endeampy)];
        ['AmpXY: ' num2str(amp)];
        ['SpeedXY: ' num2str(speed)];                
        ['MaxSpeed: ' num2str(sakkade.qmaxspeed)]                
        ['MaxSpeedPos: ' num2str(sakkade.qmaxspeedpos) '   -> ' num2str(sakkade.qmaxspeedpos_proz) ' %']});                
end



%##########################################################################
function lbSakkaden_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


%##########################################################################
function lbBlinks_Callback(hObject, eventdata, handles)
index=get(hObject,'Value');
if(isempty(handles.blinks))
    return;
end

blink=handles.blinks(index); 
if( strcmp(get(gcf,'SelectionType'),'open'))
    %clicked 2 times
    geheZu(handles,blink.bstart1);
else
    %clicked 1 time   
    set(handles.eEvent,'String',...
        {'Type: Blink';
        ['Start (Close): ' num2str(blink.bstart1)] ;
        ['End (Close): ' num2str(blink.bende1)];
        ['Amplitude (Close): ' num2str(blink.bamp1)];        
        ['StartAmp (Close): ' num2str(blink.bstartamp1)];
        ['EndAmp (Close): ' num2str(blink.bendeamp1)];
        ['MaxSpeed (Close): ' num2str(blink.qmaxspeed1)];                
        ['MaxSpeedPos (Close): ' num2str(blink.qmaxspeedpos1) '   -> ' num2str(blink.qmaxspeedpos1_proz) ' %'];                                      
         '-----------------------------';        
        ['Start (Up): ' num2str(blink.bstart2)] ;
        ['End (Up): ' num2str(blink.bende2)];
        ['Amplitude (Up): ' num2str(blink.bamp2)];                
        ['StartAmp (Up): ' num2str(blink.bstartamp2)];
        ['EndAmp (Up): ' num2str(blink.bendeamp2)];
        ['MaxSpeed (Up): ' num2str(blink.qmaxspeed2)];                
        ['MaxSpeedPos (Up): ' num2str(blink.qmaxspeedpos2) '   -> ' num2str(blink.qmaxspeedpos2_proz) ' %']});
end

  


% --- Executes during object creation, after setting all properties.
%##########################################################################
function lbBlinks_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


%##########################################################################
function eEvent_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end



%##########################################################################
function mConfig_Callback(hObject, eventdata, handles)
filterlist(); % show filter list

%load existing filter list againt
handles.filterlist=[];
if(exist('dfilter.config')==2)  
    data=load('dfilter.config','liste','-mat');    
    handles.filterlist=data.liste;   
   
    %filter data
    handles.sakkaden=filtersakkaden(handles.rawsakkaden,handles);
    handles.blinks=filterblinks(handles.rawblinks,handles);
    refresh(handles);   
end


%##########################################################################
function figure1_DeleteFcn(hObject, eventdata, handles)
if(isfield(handles,'screen') && isfield(handles.screen,'fig'))    
    if(ishandle(handles.screen.fig))     
        delete (handles.screen.fig);                 
    end
end


%##########################################################################
function mExit_Callback(hObject, eventdata, handles)
%uiresume(handles.figure1);
close



%##########################################################################
function mSave_Callback(hObject, eventdata, handles)
name='data-events';
pos=findstr(myseqreverse(handles.filename),'.');
if(~isempty(pos))
    name=[handles.filename(1:end-pos) '-events'];
end

stayontop(get(handles.figure1,'name'),false);    
[filename, pathname, filterindex] = uiputfile( ...
   {'*.txt','ASCII - numbers only (*.dat)'; ...
    '*.txt','ASCII file (*.txt)'; ...
    '*.mat','MAT file (*.mat)'; ...    
    '*.xml','XML file (*.xml)'; ...
    '*.dat','xy-Values (*.dat)';...
    '*.','Knigstein-file (*.dat)'}, ...
    'Save as ...', name);
stayontop(get(handles.figure1,'name'),...
    get(handles.cOnTop,'Value')==get(handles.cOnTop,'Max'));

if isequal(filename,0) | isequal(pathname,0)
    %Cancel
    return;
end


s=saveresult(filterindex,[pathname filename],...
        handles.reiz1,handles.reiz2,handles.blinks,handles.sakkaden,...
        adjustparameters(handles.parameter,handles.samplerate));
        

if(s)
    handles.issaved=true;
    guidata(handles.figure1, handles);
end





%##########################################################################
function mDetect_Callback(hObject, eventdata, handles)
%------------------------------------
%  adjust parameters according to sampling rate
%------------------------------------
disp(['sample freq : ' int2str(handles.samplerate) ' Hz']);

% justiere Parameter nach Samplingrate
parameter=adjustparameters(handles.parameter,handles.samplerate);

%------------------------------------
%  Analyze data
%------------------------------------
tic;

[handles.rawsakkaden, handles.rawblinks, extdata ]=...
        analyzeeog(handles.input,parameter);
toc
handles.algodata=extdata;

if(isempty(handles.rawsakkaden) && isempty(handles.rawblinks) ...
        && isempty(handles.algodata))
    disp('no events found');
    return;
end

%Filter data
handles.sakkaden=filtersakkaden(handles.rawsakkaden,handles);
handles.blinks=filterblinks(handles.rawblinks,handles);

% Determine stimulus end
dim=size(handles.input);
if(dim(2)>3 && handles.parameter.reizauswertung.xreizflg)
    handles.reiz1=findReizRob(handles.input(:,1),handles.input(:,4),handles.parameter.reizauswertung.xreiz);%Mal kurz weggemacht
else
    handles.reiz1=[];    
end

if(dim(2)>4 && handles.parameter.reizauswertung.yreizflg)
    handles.reiz2=findReizRob(handles.input(:,1),handles.input(:,5),handles.parameter.reizauswertung.yreiz);
else
    handles.reiz2=[];
end
refresh(handles);



function refresh(handles)
if(~isfield(handles,'fensterbreite'))
    %------------------------------------
    %  set display range 
    %------------------------------------
    handles.fensterbreite=6000;
    samplecount=length(handles.algodata.zeitachse);
    if(samplecount>handles.fensterbreite)    
        handles.anzeigebereich=1:handles.fensterbreite;
    else
        handles.anzeigebereich=1:samplecount;
    end

    %------------------------------------
    % Set position slider
    %------------------------------------
    if(handles.fensterbreite<samplecount)        
        %Set stepwidth
        stepratio = .1;                
        steptrough=handles.fensterbreite / (samplecount - handles.fensterbreite); % window width        
        steparrow =stepratio * steptrough;    % 10 % of window width
        set(handles.sPosition,'sliderstep', [steparrow steptrough]);
    else
        set(handles.sPosition,'Visible','off');    
    end
end


%------------------------------------
%  Fill 1st list
%------------------------------------
set(handles.lbSakkaden,'Value',1);
set(handles.lbBlinks,'Value',1);


sakkaden=handles.sakkaden;
if(~isempty(sakkaden))
    
set(handles.lbSakkaden,'String',num2str(...
    reshape([sakkaden(1:end).start],length(sakkaden),1)));
end

blinks=handles.blinks;
if(~isempty(blinks))
set(handles.lbBlinks,'String',num2str(...
    reshape([blinks(1:end).bstart1],length(blinks),1)));
end


%------------------------------------
% Create output window if there is none so far
%------------------------------------
if(~isfield(handles,'screen'))
    
    handles.screen=feval(handles.parameter.layoutgenerator);
    % Plot not closable ...
    set(handles.screen.fig,'CloseRequestFcn',[]);   

end

%------------------------------------
%  Draw graphs
%------------------------------------
rePaint(handles);

%------------------------------------
%  was not saved so far.
%------------------------------------
handles.issaved=false;
guidata(handles.figure1, handles);

%##########################################################################

function sakkaden=filtersakkaden(rawsakkaden,handles)
    
    if(strcmp(get(handles.mFilteraktiv,'Checked'),'on'))        
        sakkaden=[];
        for(i=1:length(rawsakkaden))
            sakkade=rawsakkaden(i);
            valid=true;
            for(j=1:length(handles.filterlist))
                if(~valid) break;end;
                filt=handles.filterlist(j);
                
                if(sakkade.channel==0 && filt.ishori) | ...
                   (sakkade.channel==1 && filt.isvert)
               
                      if(sakkade.channel==0)
                        amp=abs(sakkade.ampx);
                      else
                        amp=abs(sakkade.ampy);
                      end
                      dauer=sakkade.ende-sakkade.start;
                      speed=sakkade.qmaxspeed;
                    
                      if(filt.isminamp)
                          if(amp<filt.minamp) valid=false; end;
                      end  
                      if(filt.ismaxamp)
                          if(amp>filt.maxamp) valid=false; end;
                      end
                      if(filt.ismindauer)
                          if(dauer<filt.mindauer) valid=false; end;
                      end  
                      if(filt.ismaxdauer)
                          if(dauer>filt.maxdauer) valid=false; end;
                      end
                      if(filt.ismingeschw)
                          if(speed<filt.mingeschw) valid=false; end;
                      end  
                      if(filt.ismaxgeschw)
                          if(speed>filt.maxgeschw) valid=false; end;
                      end                      
                end
            end
            if(valid) sakkaden=[sakkaden sakkade]; end;
        end
    else
        sakkaden=rawsakkaden;
    end

%##########################################################################
function blinks=filterblinks(rawblinks,handles)
    blinks=rawblinks;
    


%##########################################################################
function mSetup_Callback(hObject, eventdata, handles)

stayontop(get(handles.figure1,'name'),false);    
para=zusammenfassung(handles.input,handles.parameter);
stayontop(get(handles.figure1,'name'),...
    get(handles.cOnTop,'Value')==get(handles.cOnTop,'Max'));

if isempty(para)    
    return;
end
handles.parameter=para;
guidata(handles.figure1, handles);
saveParam('lastpara.config',handles);



%##########################################################################
function figure1_CloseRequestFcn(hObject, eventdata, handles)
if ~isfield(handles, 'issaved') %RS: for some weird errors
    delete(gcf)
    delete(gcf)
    return

elseif(~handles.issaved) & exist('stayontop.dll')==3
    
stayontop(get(handles.figure1,'name'),false);    
    selection = questdlg('Save analysis?',...
                         'Quit',...
                         'Yes','No','Cancel','Yes');
stayontop(get(handles.figure1,'name'),...
    get(handles.cOnTop,'Value')==get(handles.cOnTop,'Max'));                     

    switch selection,
        case 'Abbruch'
            return;

       case 'Ja'
           mSave_Callback(hObject, eventdata, handles);          
    end
end
%uiresume(handles.figure1);
delete(gcf)




% --- Executes on button press in cOnTop.
function cOnTop_Callback(hObject, eventdata, handles)
% hObject    handle to cOnTop (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
if exist('stayontop.dll')==3
    stayontop(get(handles.figure1,'name'),...
        get(handles.cOnTop,'Value')==get(handles.cOnTop,'Max'));
    savemainconfig(handles);
else
    disp('Could not find stayontop.dll: function not possible')
end



% --------------------------------------------------------------------
function mFilteraktiv_Callback(hObject, eventdata, handles)
if(strcmp(get(handles.mFilteraktiv,'Checked'),'on'));
    set(handles.mFilteraktiv,'Checked','off');
else
    set(handles.mFilteraktiv,'Checked','on');
end

%Filtere die Daten
handles.sakkaden=filtersakkaden(handles.rawsakkaden,handles);
handles.blinks=filterblinks(handles.rawblinks,handles);

refresh(handles);
savemainconfig(handles);


% --------------------------------------------------------------------
function figure1_CreateFcn(hObject, eventdata, handles)




Contact us