R-DECO: An open-source Matlab based graphical user interface for the detection and correction of R-peaks 1.0.0
(10,017 bytes)
function varargout = QRS_selection(varargin)
% QRS_SELECTION MATLAB code for QRS_selection.fig
% QRS_SELECTION, by itself, creates a new QRS_SELECTION or raises the existing
% singleton*.
%
% H = QRS_SELECTION returns the handle to a new QRS_SELECTION or the handle to
% the existing singleton*.
%
% QRS_SELECTION('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in QRS_SELECTION.M with the given input arguments.
%
% QRS_SELECTION('Property','Value',...) creates a new QRS_SELECTION or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before QRS_selection_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to QRS_selection_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
%
% Author(s): Jonathan Moeyersons (Jonathan.Moeyersons@esat.kuleuven.be)
% Sabine Van Huffel (Sabine.Vanhuffel@esat.kuleuven.be)
% Carolina Varon (Carolina.Varon@esat.kuleuven.be)
%
% Version History:
% - 06/05/2019 JM Initial version
%
% Copyright (c) 2019, Jonathan Moeyersons, KULeuven-ESAT-STADIUS
%
% This software is made available for non commercial research purposes only
% under the GNU General Public License. However, notwithstanding any
% provision of the GNU General Public License, this software may not be
% used for commercial purposes without explicit written permission after
% contacting jonathan.moeyersons@esat.kuleuven.be
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <https://www.gnu.org/licenses/>.
% Edit the above text to modify the response to help QRS_selection
% Last Modified by GUIDE v2.5 11-Jun-2018 10:47:02
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @QRS_selection_OpeningFcn, ...
'gui_OutputFcn', @QRS_selection_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 QRS_selection is made visible.
function QRS_selection_OpeningFcn(hObject, eventdata, handles, varargin) %#ok
% 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 QRS_selection (see VARARGIN)
% Choose default command line output for QRS_selection
handles.output = hObject;
% Get sampling frequency
handles.fs = varargin{1,5};
% Get the beat length
handles.beat_length = length(varargin{1,1});
% Get the window length
handles.window = varargin{1,3};
% Set the selection based on the sign of peaks that was mostly present
if varargin{1,4} > 0
handles.selection = 1;
% Plot the QRS
handles.QRS_pos = line(handles.axes_QRS,...
1:handles.beat_length,varargin{1,1},...
'Color','b',...
'Linewidth',2,...
'Tag','Positive',...
'ButtonDownFcn', @LineCallback);
handles.QRS_neg = line(handles.axes_QRS,...
1:handles.beat_length,varargin{1,2},...
'Color','r',...
'Tag','Negative',...
'ButtonDownFcn', @LineCallback);
else
handles.selection = -1;
% Plot the QRS
handles.QRS_pos = line(handles.axes_QRS,...
1:handles.beat_length,varargin{1,1},...
'Color','b',...
'Tag','Positive',...
'ButtonDownFcn', @LineCallback);
handles.QRS_neg = line(handles.axes_QRS,...
1:handles.beat_length,varargin{1,2},...
'Color','r',...
'Linewidth',2,...
'Tag','Negative',...
'ButtonDownFcn', @LineCallback);
end
% Set the x- and y-limits
xlim(handles.axes_QRS,[0 handles.beat_length])
try
ylim(handles.axes_QRS,[min(min([handles.QRS_pos.YData handles.QRS_neg.YData])) - min(std([handles.QRS_pos.YData handles.QRS_neg.YData]))...
max(max([handles.QRS_pos.YData handles.QRS_neg.YData])) + min(std([handles.QRS_pos.YData handles.QRS_neg.YData]))])
catch
try
ylim(handles.axes_QRS,[min(handles.QRS_pos.YData) - std(handles.QRS_pos.YData)...
max(handles.QRS_pos.YData) + std(handles.QRS_pos.YData)])
catch
try
ylim(handles.axes_QRS,[min(handles.QRS_neg.YData) - std(handles.QRS_neg.YData)...
max(handles.QRS_neg.YData) + std(handles.QRS_neg.YData)])
catch
end
end
end
% Plot the R-peak line
handles.R_peak = line(handles.axes_QRS,...
[round(handles.window*handles.fs)+1 round(handles.window*handles.fs)+1], ylim(handles.axes_QRS),...
'Color','k',...
'Linewidth',1,...
'Tag','R_peak',...
'ButtonDownFcn', @LineCallback);
% Create the legend
legend(handles.axes_QRS,'Pos. R-peak','Neg. "R-peak"','R-peak location',...
'Location','eastoutside')
% Define the labels
ylabel(handles.axes_QRS,'ECG (a.u.)')
xlabel(handles.axes_QRS,'# samples')
% Enable the pointer manager and adjust the pointer
iptPointerManager(handles.figure1,'enable');
% Change the pointer behavior for the lines
pointerBehavior.enterFcn = [];
pointerBehavior.exitFcn = [];
pointerBehavior.traverseFcn = @overline;
iptSetPointerBehavior(handles.R_peak, pointerBehavior);
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes QRS_selection wait for user response (see UIRESUME)
uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = QRS_selection_OutputFcn(hObject, eventdata, handles) %#ok
% 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.selection;
varargout{2} = handles.R_peak.XData(1) - (round(handles.window*handles.fs)+1);
% Delete the figure
delete(handles.figure1);
% --- Executes on button press in pushbutton_accept.
function pushbutton_accept_Callback(hObject, eventdata, handles) %#ok
% hObject handle to pushbutton_accept (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
uiresume(handles.figure1)
% Helper functions
function LineCallback(hObject, eventdata)
% hObject handle to selected line (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% Get the handles
handles = guidata(eventdata.Source);
switch hObject.Tag
case 'Positive'
set(handles.QRS_pos,'Linewidth',2)
set(handles.QRS_neg,'Linewidth',0.5)
handles.selection = 1;
case 'Negative'
set(handles.QRS_pos,'Linewidth',0.5)
set(handles.QRS_neg,'Linewidth',2)
handles.selection = -1;
case 'R_peak'
set(handles.QRS_pos,'Linewidth',0.5)
set(handles.QRS_neg,'Linewidth',0.5)
set(handles.R_peak,'Linewidth',2)
% Disable the pointer manager
iptPointerManager(handles.figure1,'disable');
% Fix the pointer to left
set(handles.figure1,'Pointer','left')
set(handles.figure1,'WindowButtonMotionFcn',{@move_R_peak,handles},...
'WindowButtonUpFcn',{@define_R_peak,handles})
end
% Update handles structure
guidata(hObject, handles);
function move_R_peak(hObject, eventdata, handles) %#ok
% Get the mouse position
mousepos = get(handles.axes_QRS,'CurrentPoint');
if mousepos(1) <= 1 % Past the left limit
idx = 1;
elseif mousepos(1) >= handles.beat_length % Past the right limit
idx = handles.beat_length;
else % Perfect
idx = round(mousepos(1));
end
% Adjust the temporary R-peak
set(handles.R_peak,'XData',[idx idx])
% Update structure
guidata(hObject,handles);
function define_R_peak(hObject, eventdata, handles) %#ok
% Remove the window button motion and up function
set(handles.figure1,'WindowButtonMotionFcn','',...
'WindowButtonUpFcn','');
% Change the linewidth back to previous
switch handles.selection
case 1
set(handles.QRS_pos,'Linewidth',2)
set(handles.QRS_neg,'Linewidth',0.5)
case -1
set(handles.QRS_pos,'Linewidth',0.5)
set(handles.QRS_neg,'Linewidth',2)
end
set(handles.R_peak,'Linewidth',1)
% Change the pointer back to it's original state
set(handles.figure1,'Pointer','arrow')
% Enable the pointer manager and adjust the pointer
iptPointerManager(handles.figure1,'enable');
% Change the pointer behavior for the lines
pointerBehavior.enterFcn = [];
pointerBehavior.exitFcn = [];
pointerBehavior.traverseFcn = @overline;
iptSetPointerBehavior(handles.R_peak, pointerBehavior);
% Update structure
guidata(hObject,handles);